2
votes

I am new to OpenCv. I am trying to create a white and black cartoonist picture of person through OpenCV in python. I am kind of successful, in creating black and white cartoon type picture of person. But the problem is, I want to remove black little dots from the output image. Please help me. I want to remove these black dots as pointed in picture. Here is my code.

    image = cv2.imread('input1.jpg')
    img_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    img_gray = cv2.medianBlur(img_gray, 5)
    edges = cv2.Laplacian(img_gray, cv2.CV_8U, ksize=5)
    ret,mask =cv2.threshold(edges,100,255,cv2.THRESH_BINARY_INV)
    image2 = cv2.bitwise_and(image, image, mask=mask)
    cv2.imshow("Mask", mask)

enter image description here

2
you could try performing median blur on the final image again - Jeru Luke
Added some code to my answer, try applying median filter another time after you convert the image to binary :) - George K
The kid is scary BTW... - lucians
The kid is NOT scary. My code made him scary. - Hasnain

2 Answers

2
votes

You need to apply a filter to your image using OpenCV to remove the black dots (which are called "noise"). There are many 2D convolutions you can apply to the image.

Median Filter

This filter will find the median value of every pixel and its surrounding pixels. It can gather as many pixels away from the centre as you like amplifying the effect.

Gaussian Blur

You can apply another type of blurring which should remove noise, maybe not entirely but it will surely reduce it's effect. If you're working on black and white, which it seems you are, then this might actually remove noise entirely.

Edit

Try applying a median filter again after you apply the threshold, that should remove noise much better than before since the values are binary:

image = cv2.imread('input1.jpg')
img_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
img_gray = cv2.medianBlur(img_gray, 5)
edges = cv2.Laplacian(img_gray, cv2.CV_8U, ksize=5)
ret,mask =cv2.threshold(edges,100,255,cv2.THRESH_BINARY_INV)
image2 = cv2.bitwise_and(image, image, mask=mask)
image2 = cv2.medianBlur(image2, 3)  # this
cv2.imshow("Mask", mask)

Hope this helps!

0
votes

You could also try to find little countours and draw them out. Something like this:

img = cv2.imread('input1.jpg')
imgray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret,thresh = cv2.threshold(imgray,220,255,0)
_, contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
number_contours = len(contours)
print(number_contours)
for i in range(0, number_contours):
    lenght = cv2.contourArea(contours[i])
    if float(1)<lenght<float(5000):
        cv2.drawContours(img, contours[i], 0, (255,255,255), 7)
cv2.imshow("image", img)
cv2.imwrite("brez_pikic.jpg", img)

enter image description here