6

I am having a problem regarding the kernel size for morphologyEx. I have some captcha images and I want to do the same operation on them and get the same final result.

code :

image = cv2.imread("Image.jpg")
gray = cv2.cvtColor(image , cv2.COLOR_BGR2GRAY)


ret, thresh1 = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)

k1 = np.ones((3,3))
k2 = np.ones((5,5))
bottom_image = cv2.morphologyEx(thresh1, cv2.MORPH_CLOSE, k1)
bottom_image =  255-bottom_image
bottom_image = remove_boxes(bottom_image , True)


ret,thresh2 = cv2.threshold(bottom_image,127,255,cv2.THRESH_BINARY_INV)
opening = cv2.morphologyEx(thresh2, cv2.MORPH_OPEN, k1)


#closing =  cv2.morphologyEx(opening, cv2.MORPH_CLOSE, k)
# cv2.imshow('opening', opening)

dilate = cv2.morphologyEx(opening, cv2.MORPH_DILATE, k2)
dilate = cv2.bitwise_not(dilate)
# cv2.imshow('dilation', dilate)


bottom_image = cv2.morphologyEx(bottom_image, cv2.MORPH_CLOSE, k1)

The perfect result would be

Input:
enter image description here

Output:
enter image description here

But the problem appears when I apply it to other images with the same structure output is distorted.

Example 1 :

Input:
enter image description here

Output:
enter image description here

Example 2 :

Input:
enter image description here

Output:
enter image description here

Example 3:

Input:
enter image description here

Output:
enter image description here

Ramesh-X
  • 4,853
  • 6
  • 46
  • 67
ahmed osama
  • 621
  • 2
  • 12
  • 21
  • It's not very productive to post the same question for different images. Gather samples of all your images, resize them to thumbnail size, stitch them all together. Post a single question with that image as input. – zindarod Jun 24 '18 at 10:51
  • ok, I am removing the duplicates now. – ahmed osama Jun 24 '18 at 10:52

1 Answers1

8

This answer was inspired by this excellent post.

import numpy as np
import cv2

if __name__ == '__main__':

    image = cv2.imread('image.png',cv2.IMREAD_UNCHANGED)

    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

    ret,binary = cv2.threshold(gray, 0, 255, cv2.THRESH_OTSU | cv2.THRESH_BINARY)

    binary = cv2.bitwise_not(binary)

    H = cv2.Sobel(binary, cv2.CV_8U, 0, 2)
    V = cv2.Sobel(binary, cv2.CV_8U, 2, 0)

    rows,cols = image.shape[:2]

    _,contours,_ = cv2.findContours(V, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)

    for cnt in contours:
        (x,y,w,h) = cv2.boundingRect(cnt)
        # rows/3 is the threshold for length of line
        if h > rows/3:
            cv2.drawContours(V, [cnt], -1, 255, -1)
            cv2.drawContours(binary, [cnt], -1, 255, -1)
        else:
            cv2.drawContours(V, [cnt], -1, 0, -1)

    _,contours,_ = cv2.findContours(H, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)

    for cnt in contours:
        (x,y,w,h) = cv2.boundingRect(cnt)
        # cols/3 is the threshold for length of line
        if w > cols/3:
            cv2.drawContours(H, [cnt], -1, 255, -1)
            cv2.drawContours(binary, [cnt], -1, 255, -1)
        else:
            cv2.drawContours(H, [cnt], -1, 0, -1)

    kernel = cv2.getStructuringElement(shape=cv2.MORPH_RECT, ksize=(3,3))
    H = cv2.morphologyEx(H, cv2.MORPH_DILATE, kernel,iterations = 3)
    V = cv2.morphologyEx(V, cv2.MORPH_DILATE, kernel, iterations = 3)

    cross = cv2.bitwise_and(H, V)

    _,contours,_ = cv2.findContours(cross,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)
    centroids = []
    for cnt in contours:
        mom = cv2.moments(cnt)
        (x,y) = mom['m10']/mom['m00'], mom['m01']/mom['m00']
        cv2.circle(image,(int(x),int(y)),4,(0,255,0),-1)
        centroids.append((x,y))

    centroids.sort(key = lambda x: x[0], reverse = False)
    centroids.sort(key = lambda x: x[1], reverse = False)

    dx = int(centroids[1][0] - centroids[0][0])
    centroids = np.array(centroids, dtype = np.float32)
    (x,y,w,h) = cv2.boundingRect(centroids)

    if x-dx > -5: x = max(x-dx,0)
    if h+dx <= rows+5: h = min(h+dx,rows)
    if w+dx <= cols+5: w = min(w+dx,cols)
    cv2.rectangle(image, (x,y), (x+w,y+h), (0,255,0))

    roi = binary[y:y+h,x:x+w]

    roi = cv2.morphologyEx(roi, cv2.MORPH_OPEN, kernel,iterations = 1)

    cv2.imshow('image', image)
    cv2.imshow('roi', roi)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

1

2

3

4

zindarod
  • 6,328
  • 3
  • 30
  • 58
  • Hi Zindarod. Thanks for your help. Can you please add some comments to the code and why do you choose static numbers. – ahmed osama Jun 26 '18 at 14:31
  • @ahmedosama See the new code. I don't have the time to fully comment the code right now. – zindarod Jun 26 '18 at 14:42
  • Ok, Last code mostly solve the problem .But small thing i found this code modify image size . I would like to keep image same size . I think about embedding `roi` in to same size of the input image . Do you have a better solution – ahmed osama Jun 26 '18 at 18:41
  • @ahmedosama If you don't want the ROI then the code will be even easier. I leave that solution to you. Hint: There's no need to compute the lines intersection. – zindarod Jun 26 '18 at 18:55
  • @JeruLuke Thanks. – zindarod Jun 27 '18 at 08:13
  • @zindarod I have a problem in the code: dx = int(centroids[1][0] - centroids[0][0]) IndexError: list index out of range. How to solve? – Tecnologia da Net Nov 09 '18 at 23:15