2
votes

I have the following code:

    import cv2
    import numpy as np
    import matplotlib
    import matplotlib.pyplot as plt
    from skimage import data
    from skimage import filter
    from skimage.filter import threshold_otsu

    matplotlib.rcParams['font.size'] = 9

    nomeimg = 'frame1_depth.png'

    i = cv2.imread(nomeimg, -1)
    #conversione da 16 a 32 uint
    img = np.array(i, dtype=np.uint32)
    img *= 65536
    print img.dtype

    #thresholding con il metodo Otsu 
    thresh = threshold_otsu(img)
    binary = img > thresh
    print thresh

    plt.figure(1)
    fig, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize=(8, 2.5))
    ax1.imshow(img)
    ax1.set_title('Original')
    ax1.axis('off')

    ax2.hist(img)
    ax2.set_title('Histogram')
    ax2.axvline(x=thresh, color='r', linestyle='dashed', linewidth=2)

    ax3.imshow(binary, cmap=plt.cm.gray)
    ax3.set_title('Thresholded')
    ax3.axis('off')

    plt.figure(2)
    f, ax = plt.subplots(figsize=(8, 2.5))
    ax.imshow(binary, cmap=plt.cm.gray)
    ax.set_title('Thresholded')
    ax.axis('off')

    plt.show()

I have a set of depth images from the XBOX kinect, and so after a data type conversion so that I can use some opencv functions which work only with 8 or 32 bit images, I've thresholded the image with the Otsu algorithm and showed the results.

I have obtained a subplot in which I have my original image, the histogram and the thresholded black and white image. Now I want to work only on this black and white image and I want to save it and compute contours, the convex hull and others geometrical features. However, it's just thresholded, but with otsu.

How can I compute this?

1

1 Answers

4
votes

If you want to work with findContours and other image processing analysis functions in OpenCV with your binary image, you simply need to take binary and convert it to uint8. Also, make sure you scale your image so that the non-zero values become 255. uint32 will only work under certain modes, and to avoid any unnecessary headaches in remembering which modes from which functions allow you to do this, just stick with uint8

As such, do this:

binary = 255*(binary.astype('uint8'))

Once you do this conversion, you can then call findContours:

contours, hierarchy = cv2.findContours(binary,cv2.RETR_LIST,cv2.CHAIN_APPROX_NONE)

The above is just one way to call it. I would recommend you look at the documentation for more details, which I've linked above.


As another example, if you want to find the convex hull of your thresholded image, which has a bunch of shapes via convexHull, you would need a set of points that represent your contours, which is exactly given by the contours output of cv2.findContours. However, the convexHull function assumes there is only a single object that represents one contour. If you have multiple objects and thus multiple contors, you'll have to iterate over each contour and store the results.

As such, do something like this:

hull = [cv2.convexHull(cnt) for cnt in contours]

Each element in hull will return the coordinates that compose of the convex hull for each contour. As such, to access the coordinates of the convex hull for contour i, you would do:

points = hull[i]

BTW, here are a couple of great links to get you started with OpenCV's shape analysis functions. Here's a link that talks about how to use cv2.findContours in a more general context:

http://opencv-python-tutroals.readthedocs.org/en/latest/py_tutorials/py_imgproc/py_contours/py_contours_begin/py_contours_begin.html

Here's another link that talks about OpenCV's other shape analysis functions, such as convex hull, image moments, etc.:

http://opencv-python-tutroals.readthedocs.org/en/latest/py_tutorials/py_imgproc/py_contours/py_contour_features/py_contour_features.html

Have fun!