opencvcomputer-visioncontourconvolutionlowpass-filter

how to find contours on a low pass filtered image?


I am new to computer visions. So I dont know the internal implementation of the following code because of which I am unable to debug the error. Can anyone please point out the error in the following code?

The code is converting a parking image into binary using the combination of Box Filter and Edge detection Kernel matrix. And then I am trying to find the contours. Now I know that contour is found out on the binary image which can be derived out using cv2.threshold() function, isnt the image obtained from Filter and Kernel matrix also a binary image?

import cv2
import numpy as np
import matplotlib.pyplot as plt

img=cv2.imread('parking spot1.jpg',1)
k3 = np.array(([-1,-1,-1],[-1,8,-1],[-1,-1,-1]))
low_filter = cv2.boxFilter(img, -1, (4,4))
output_low = cv2.filter2D(low_filter, -1, k3)
plt.subplot(2, 2, 1)
plt.imshow(img)
plt.title('Original Image')

plt.subplot(2, 2, 2)
plt.imshow(output_low)
plt.title('matrix1')

plt.show()

img, ret, heirarchy = cv2.findContours(output_low, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

What do you think I am doing wrong? I would really appreciate an explanation or a direction in this issue.

Thanks a lot in advance.

The error that I am facing is:


Traceback (most recent call last) in () ----> 1 img, ret, heirarchy = cv2.findContours(output_low, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

error: OpenCV(3.4.3) /io/opencv/modules/imgproc/src/contours.cpp:199: error: (-210:Unsupported format or combination of formats) [Start]FindContours supports only CV_8UC1 images when mode != CV_RETR_FLOODFILL otherwise supports CV_32SC1 images only in function 'cvStartFindContours_Impl


Solution

  • Please read the documentation of filtering properly. It is clearly stated that output has the same size and type as source. Therefore your output_low is three dimensional and cv2.findContours cannot be applied to it. You can take a threshold as you have stated or can simply convert output_low to grayscale and then find contours.

    EDIT

    I guess my answer was not clear in stating the difference between channels and the depth of the image. The image obtained from filter and kernel matrix is not necessarily one dimensional or grayscale. It has the same size as the input matrix and that means the number of channels is also equal. Therefore if your input image is in grayscale then the output will be one dimensional.

    You can refer here to read more about the difference between channels and depth.

    box filter documentation

    filter2d documentation

    Therefore if you want the results of cv2.boxFilter and cv2.filter2D in grayscale just convert the original image to grayscale before applying filtering on it.

    img = cv2.imread('opencv1.png', 1)
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    k3 = np.array(([-1,-1,-1],[-1,8,-1],[-1,-1,-1]))
    low_filter = cv2.boxFilter(gray, -1, (4,4))
    output_low = cv2.filter2D(low_filter, -1, k3)
    

    Your error clearly states that FindContours supports only CV_8UC1 images when mode != CV_RETR_FLOODFILL otherwise supports CV_32SC1 images. The C1 in CV_8UC1 and CV_32SC1 denotes that the number of channels can only be one.