How to clean (delete) a black frame/boundaries/countour at the edges of the image after adaptive thresholding

220 Views Asked by At

I applied adaptive gaussian thresholding to my .tif image, but the black frame (contour) on the edges was created. Can't understand why and how to delete.

I would be very grateful for your help! p.s. After cv2.threshold(img,127,255,cv2.THRESH_BINARY) there is no frame.

This is my original image:

https://drive.google.com/file/d/1DfdmQQ9AS-U2SXtyJzU94oYsLLSUmV7N/view?usp=share_link

This is fragment of my image (colored) and after gaussian thresholding (white and black). The black countour on the edge of the image is clearly visible. enter image description here

My code:

img = cv2.imread(" My.tiff", 0)

th = cv2.adaptiveThreshold(img,255,cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY,115,2)

Tried this (found on the Stack overflow), but no results:

img = cv2.imread(file_path, 0)

rows, cols = img.shape

cv2.floodFill(img, None, seedPoint=(0, 0), newVal=255, loDiff=1, upDiff=1)  # Fill the top left corner.
cv2.floodFill(img, None, seedPoint=(cols-1, 0), newVal=255, loDiff=1, upDiff=1)  # Fill the top right corner.
cv2.floodFill(img, None, seedPoint=(0, rows-1), newVal=255, loDiff=1, upDiff=1)  # Fill the bottop left corner.
cv2.floodFill(img, None, seedPoint=(cols-1, rows-1), newVal=255, loDiff=1, upDiff=1)  # Fill the bottom right corner.

My image after adaptive gaussian thresholding (thresholding is ok..but why the black border was created and how to remove it, unfortunately, can't understand): enter image description here

1

There are 1 best solutions below

1
On BEST ANSWER

The black edge is a result of the steep change in gray levels between the image data, and the white margins.

For fixing the issue, we may fill the margins with values that are closer to the pixels of the image, apply adaptiveThreshold, and restore the margins.

Filling the margins with values that are closer to the pixels is not so simple.
Assuming the image is relatively homogeneous we may apply the following stages for covering the white margins:

  • Resize the image by a factor of 1.5 in each axis (1.5 factor is about sqrt(2) that applies 45 degree rotation).
  • Blur the resized image with a large kernel.
  • Crop the center that is the same size as the original image.
  • Replace the white margins with the matching pixels in the resized, blurred cropped image.

After covering the margins, execute adaptiveThreshold, and fill the margins with zeros.


Code sample:

import cv2
import numpy as np

img = cv2.imread('ndsi.tiff')

# Assume the margins are white, and there are very few white pixels in the other parts of the image.
# Create a mask with True where pixel are white and False otherwise.
mask = np.all(img != 255, axis=-1).astype(np.uint8)*255

img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  # Convert to grayscale.

# Apply morphological closing for removing small white parts inside the image.
# Note for getting a better mask, we may find minAreaRect as suggested by Micka
#mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, np.ones((5, 5), np.uint8))


#mask = cv2.erode(mask, np.ones((5, 5), np.uint8))  # Erode the mask, because there are too many artifacts

# Resize the image by a factor of 1.5 in each axis
resized_img = cv2.resize(img, (img.shape[1]*3//2, img.shape[0]*3//2))

# Blur with large kernel
resized_img_blurred = cv2.GaussianBlur(resized_img, (51, 51), 50)

# Crop the center that is the same size as the original image.
center_img_blurred = resized_img_blurred[(resized_img.shape[0] - img.shape[0])//2:(resized_img.shape[0] + img.shape[0])//2, (resized_img.shape[1] - img.shape[1])//2:(resized_img.shape[1] + img.shape[1])//2]

tmp_img = img.copy()
tmp_img[mask==0] = center_img_blurred[mask==0]  # Replace white margins with resized blurred image.

# Apply the threshold on tmp_img 
th = cv2.adaptiveThreshold(tmp_img, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 11, 2)

# Remove the margins from th
th[mask == 0] = 0

# Show images for testing:
cv2.imshow('mask', cv2.resize(mask, (1024, 1024)))
cv2.imshow('center_img_blurred', cv2.resize(center_img_blurred, (1024, 1024)))
cv2.imshow('tmp_img', cv2.resize(tmp_img, (1024, 1024)))
cv2.imshow('th', cv2.resize(th, (1024, 1024)))
cv2.waitKey()
cv2.destroyAllWindows()

cv2.imwrite('tmp_img.jpg', cv2.resize(tmp_img, (1024, 1024)))
cv2.imwrite('th.png', cv2.resize(th, (1024, 1024)))

Result:
enter image description here

tmp_img:
enter image description here