shurup
shurup

Reputation: 871

How to smooth and make thinner these very rough images using OpenCV?

I have some black and white images of a single digit. I am using a NN model trained on MNIST to classify them. However, the digits are too rough and thick compared to the MNIST dataset. For example:

enter image description here

TLDR: I need to smoothen image and possibly make overall shape thinner using OpenCV.

Upvotes: 1

Views: 2905

Answers (2)

fmw42
fmw42

Reputation: 53164

You can use a combination of morphology close, open and erode (and optionally skeletonize and dilate) in Python/OpenCV as follows:

Input:

enter image description here

import cv2
import numpy as np
from skimage.morphology import skeletonize

# load image
img = cv2.imread("5.png")

# convert to gray
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# threshold image
thresh = cv2.threshold(gray,0,255,cv2.THRESH_BINARY)[1]

# apply morphology close
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (11,11))
thresh = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)

# apply morphology open
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (11,11))
thresh = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)

# apply morphology erode
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (21,21))
thresh = cv2.morphologyEx(thresh, cv2.MORPH_ERODE, kernel)

# write result to disk
cv2.imwrite("5_thinned.png", thresh)

# skeletonize image and dilate
skeleton = cv2.threshold(thresh,0,1,cv2.THRESH_BINARY)[1]
skeleton = (255*skeletonize(skeleton)).astype(np.uint8)
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (15,15))
skeleton_dilated = cv2.morphologyEx(skeleton, cv2.MORPH_DILATE, kernel)

# write result to disk
cv2.imwrite("5_skeleton_dilated.png", skeleton_dilated)

cv2.imshow("IMAGE", img)
cv2.imshow("RESULT1", thresh)
cv2.imshow("RESULT2", skeleton_dilated)
cv2.waitKey(0)
cv2.destroyAllWindows()


Result1 (close, open, erode):

enter image description here

Result2 (close, open, erode, skeletonize, dilate):

enter image description here

Upvotes: 3

Warpstar22
Warpstar22

Reputation: 613

You will most likely benefit from morphological operations. Specifically it sounds like you want erosion.

You do have some noise though. You should try OpenCV's smoothing operations. Based on my experience, I think you need to use a median blur with a kernel area of maybe around 9 (although it depends on what you want). Then you need to use erode.

Upvotes: 1

Related Questions