pythonopencvcontourbinary-image

Crop the specific color region and remove the noisy regions (Python+OpenCV)


I have a problem while getting a binary image from colored images. cv2.inRange() function is used to get mask of an image (simillar with thresholding) and I want to delete unnecessary parts, minimizing erosion of mask images. The biggest problem is that masks are not regularly extracted.

Samples

Crack:

crack

Typical one

typical one

Ideal one:

ideal one

My first object is making second picture as third one. I guess getting contour that has biggest area and deleting other contours(also for the mask) would be work. But can't not find how.

Second probleme is that the idea I described above would not work for the first image(crack). This kind of images could be discarded. But anyway it should be labeled as crack. In so far, I don't have ideas for this.

What I did

Here is input image and codes 42_1.jpg

class Real:
    __ex_low=np.array([100,30,60])
    __ex_high=np.array([140,80,214])

    __ob_low=np.array([25,60,50]) #27,65,100])
    __ob_high=np.array([50,255,255]) #[45,255,255])

    def __opening(self, mask):
        kernel = np.ones((3,3), np.uint8)
        op = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel)
        return op

    def __del_ext(self, img_got):
        img = img_got[0:300,]
        hsv = cv2.cvtColor(img,cv2.COLOR_BGR2HSV)
        mask = cv2.inRange(hsv, self.__ex_low, self.__ex_high)

        array1 = np.transpose(np.nonzero(mask))
        array2 = np.nonzero(mask)
        temp=array1.tolist()

        xmin=min(array2[0])     #find the highest point covered blue
        x,y,channel=img.shape
        img=img[xmin:x,]
        hsv=hsv[xmin:x,]

        return img, hsv


    def __init__(self, img_got):
        img, hsv = self.__del_ext(img_got)

        mask_temp = cv2.inRange(hsv, self.__ob_low, self.__ob_high)
        mask = self.__opening(mask_temp)

        array1 = np.transpose(np.nonzero(mask))
        array2 = np.nonzero(mask)

        ymin=min(array2[1])
        ymax=max(array2[1])
        xmin=min(array2[0])
        xmax=max(array2[0])

        self.x = xmax-xmin
        self.y = ymax-ymin
        self.ratio = self.x/self.y

       # xmargin = int(self.x*0.05)
        #ymargin = int(self.y*0.05)

        self.img = img[(xmin):(xmax),(ymin):(ymax)]
        self.mask = mask[(xmin):(xmax),(ymin):(ymax)]

#models = glob.glob("D:/Python36/images/motor/*.PNG")
img = cv2.imread("D:/Python36/images/0404/33_1.jpg")#<- input image

#last_size = get_last_size(models[-1])
#m2= Model(models[39],last_size)

r1 = Real(img)


cv2.imshow("2",r1.img)
cv2.imshow("3",r1.mask)

It would be great if codes are written in python3, but anything will be okay.


Solution

  • In general, you method is ok, except the wrong kernel to remove the horizontal lines.

    I finish it by in following steps:

    (1) Read and convert to HSV

    (2) Find the target yellow color region in HSV

    (3) morph-op to remove horizone lines

    (4) crop the region

    This is the result:

    enter image description here


    The code:

    #!/usr/bin/python3
    # 2018/04/16 13:20:07
    # 2018/04/16 14:13:03
    
    import cv2
    import numpy as np
    
    ## (1) Read and convert to HSV
    img = cv2.imread("euR2X.png")
    hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
    
    ## (2) Find the target yellow color region in HSV
    hsv_lower = (25, 100, 50)
    hsv_upper = (33, 255, 255)
    mask = cv2.inRange(hsv, hsv_lower, hsv_upper)
    
    ## (3) morph-op to remove horizone lines
    kernel = np.ones((5,1), np.uint8)
    mask2 = cv2.morphologyEx(mask, cv2.MORPH_OPEN,  kernel)
    
    
    ## (4) crop the region
    ys, xs = np.nonzero(mask2)
    ymin, ymax = ys.min(), ys.max()
    xmin, xmax = xs.min(), xs.max()
    
    croped = img[ymin:ymax, xmin:xmax]
    
    pts = np.int32([[xmin, ymin],[xmin,ymax],[xmax,ymax],[xmax,ymin]])
    cv2.drawContours(img, [pts], -1, (0,255,0), 1, cv2.LINE_AA)
    
    
    cv2.imshow("croped", croped)
    cv2.imshow("img", img)
    cv2.waitKey()
    

    References:

    1. what are recommended color spaces for detecting orange color in open cv?

    2. Find single color, horizontal spaces in image