I am trying to come up with a way to get rid of tinier and smaller details from a single larger contour, that I am able to find in an image.
import cv2
import numpy as np
image_vec = cv2.imread('0000000000.eigo.png', cv2.COLOR_BGR2GRAY)
g_blurred = cv2.GaussianBlur(image_vec, (5, 5), 0)
blurred_float = g_blurred.astype(np.float32) / 255.0
edgeDetector = cv2.ximgproc.createStructuredEdgeDetection("model.yml")
edges = edgeDetector.detectEdges(blurred_float) * 255.0
cv2.imwrite('edge-raw.jpg', edges)
def SaltPepperNoise(edgeImg):
count = 0
lastMedian = edgeImg
median = cv2.medianBlur(edgeImg, 3)
while not np.array_equal(lastMedian, median):
zeroed = np.invert(np.logical_and(median, edgeImg))
edgeImg[zeroed] = 0
count = count + 1
if count > 70:
break
lastMedian = median
median = cv2.medianBlur(edgeImg, 3)
edges_ = np.asarray(edges, np.uint8)
SaltPepperNoise(edges_)
cv2.imwrite('edge.jpg', edges_)
#canny edge detection
edges_ = cv2.Canny(edges_, 50, 255)
edges_ = cv2.GaussianBlur(edges_, (5, 5), 0)
cv2.imwrite('edgecanny.png', edges_)
def findSignificantContour(edgeImg):
contours, hierarchy = cv2.findContours(
edgeImg,
cv2.RETR_TREE,
cv2.CHAIN_APPROX_SIMPLE
)
# Find level 1 contours
level1Meta = []
for contourIndex, tupl in enumerate(hierarchy[0]):
# Filter the ones without parent
if tupl[3] == -1:
tupl = np.insert(tupl.copy(), 0, [contourIndex])
level1Meta.append(tupl)
contoursWithArea = []
for tupl in level1Meta:
contourIndex = tupl[0]
contour = contours[contourIndex]
area = cv2.contourArea(contour)
contoursWithArea.append([contour, area, contourIndex])
contoursWithArea.sort(key=lambda meta: meta[1], reverse=True)
largestContour = contoursWithArea[0][0]
return largestContour
contour = findSignificantContour(edges_)
contourImg = np.copy(image_vec)
cv2.drawContours(contourImg, [contour], 0, (0, 255, 0), 2, cv2.LINE_AA, maxLevel=1)
cv2.imwrite('contour.jpg', contourImg)
hh, ww = image_vec.shape[:2]
mask = np.zeros((hh,ww), dtype=np.uint8)
cv2.drawContours(mask, [contour], 0, (255,255,255), cv2.FILLED)
# invert mask so shapes are white on black background
mask_inv = 255 - mask
# create new (blue) background
bckgnd = np.full_like(image_vec, (255,0,0))
# apply mask to image
image_masked = cv2.bitwise_and(image_vec, image_vec, mask=mask)
# apply inverse mask to background
bckgnd_masked = cv2.bitwise_and(bckgnd, bckgnd, mask=mask_inv)
# add together
result = cv2.add(image_masked, bckgnd_masked)
cv2.imwrite("imwrite.png", result)
Input Image:
Output Image:
Desired output:
This happens with all images.
I have tried using erosion and dilation, but that works differently with every image.
I was wondering if there is a way I can find two close pixels that are not connected, forming a branch, then connect those two pixels.
I will have a single huge contour in every image I pass, so there is no question of overlapping or smaller but useful contours.