Reputation: 871
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:
TLDR: I need to smoothen image and possibly make overall shape thinner using OpenCV.
Upvotes: 1
Views: 2905
Reputation: 53164
You can use a combination of morphology close, open and erode (and optionally skeletonize and dilate) in Python/OpenCV as follows:
Input:
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):
Result2 (close, open, erode, skeletonize, dilate):
Upvotes: 3
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