[Python] Edge (Contour) Detection For Rocks / Stones With Watershed Segmentation

Discussão em 'Python' iniciado por Stack, Março 27, 2025.

  1. Stack

    Stack Membro Participativo

    My topic is to determine sizes of rocks / stones with image processing and I need help with edge or contour detection (image segmentation) for these rock pictures. After contour detection, I will calculate sizes of the rocks easily (I found some python code that is working enough for me).

    After my researches in the literature, I think, the best edge detection algorithm is to use watershed segmentation in my work, but if you advise another method, I can work with it.

    At the end of my calculations, I must have the following results, indicating lines after segmentations:

    Edge Detection Example 1:

    Edge Detection Example 2:

    Edge Detection Example 3:

    After my trials in python, I am finding the following results:

    My Calculation Example 1:

    My Calculation Example 2:

    My Calculation Example 3:

    My Calculation Example 4:

    My Calculation Example 5:

    If you look at my results, my results are shown not good in all examples. I change image brightness, image gamma, filtering parameters, watershed parameters, however, not of them worked correctly for my ideal solution. I am new in image processing and python and if I make a mistake, can you say any idea for that?

    My code is the following:

    import cv2
    import numpy as np
    from IPython.display import Image, display
    from matplotlib import pyplot as plt
    from skimage import io, img_as_float, color, measure, img_as_ubyte
    from skimage.segmentation import clear_border
    from skimage.restoration import (denoise_tv_chambolle,denoise_bilateral,denoise_wavelet,estimate_sigma)
    from PIL import Image
    from PIL import ImageEnhance

    path = 'OrijinalKaya5.jpg'

    #BRIGHTNESS SETTING
    image=Image.open(path)
    enhancer=ImageEnhance.Brightness(image)
    brightness_factor=**1.3**
    brightened_image=enhancer.enhance(brightness_factor)
    brightened_image.save('Brightened.jpg')

    brightened_img=cv2.imread('Brightened.jpg')

    #GAMMA SETTING
    gamma=**1.45**
    invGamma = 1.0 / gamma
    table = np.array([((i / 255.0) ** invGamma) * 255
    for i in np.arange(0, 256)]).astype("uint8")
    gamma_img=cv2.LUT(brightened_img, table)
    cv2.imwrite('Gamma.jpg',gamma_img)


    path='Gamma.jpg'

    img_ori = img_as_float(io.imread(path))

    # Bilateral Filter
    #denoise = denoise_bilateral(img_ori, sigma_color=**0.03**, sigma_spatial=**0.9**, channel_axis=-1)

    # Total Variation Filter
    denoise = denoise_tv_chambolle(img_ori, weight=**0.01**, channel_axis=-1)

    # Wavelet Denoising
    #denoise = denoise_wavelet(img_ori, channel_axis=-1, rescale_sigma=True)

    # Wavelet Denoising in YCbCr Colorspace
    #denoise = denoise_wavelet(img_ori, channel_axis=-1, convert2ycbcr=True, rescale_sigma=True)

    denoise_img_ubyte = img_as_ubyte(denoise)

    # turn into gray scale
    gray = denoise_img_ubyte.astype("uint8")
    gray=cv2.cvtColor(gray, cv2.COLOR_BGR2GRAY)


    # tresholding
    ret, bin_img = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)

    # smoothing the image
    kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3,3))
    #kernel = np.ones((**5,5**), np.uint8)
    #bin_img = cv2.morphologyEx(bin_img, cv2.MORPH_CLOSE, kernel, iterations=**3**)
    bin_img = cv2.morphologyEx(bin_img, cv2.MORPH_OPEN, kernel, iterations=**2**)

    # removal of the objects that touch the edge of the image
    bin_img = clear_border(bin_img)

    # sure background area
    sure_bg = cv2.dilate(bin_img, kernel, iterations=**30**)

    # Distance transform
    dist = cv2.distanceTransform(bin_img, **cv2.DIST_L2**, 3)

    # Make the distance transform normal.
    dist = cv2.normalize(dist, None, 0, 1.0, cv2.NORM_MINMAX)

    # foreground area
    ret, sure_fg = cv2.threshold(dist, **0.15** * dist.max(), 255, cv2.THRESH_BINARY)
    sure_fg = sure_fg.astype(np.uint8)

    # unknown area
    unknown = cv2.subtract(sure_bg, sure_fg)

    # Marker labelling sure foreground
    ret, markers = cv2.connectedComponents(sure_fg)
    markers += 255
    markers[unknown == 255] = 0

    # watershed Algorithm
    gray = cv2.cvtColor(gray, cv2.COLOR_GRAY2RGB)
    markers = cv2.watershed(gray, markers)

    # drawing contours from color marks
    labels = np.unique(markers)

    coins = []
    for label in labels[3:]:
    target = np.where(markers == label, 255, 0).astype(np.uint8)
    contours, hierarchy = cv2.findContours(target, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

    coins.append(contours[0])

    #img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    img = cv2.drawContours(img_ori, coins, -1, color=(0, 255, 0), thickness=2)

    img2 = color.label2rgb(markers, bg_label=255)
    img2[img2 == 0] = 0

    # display results
    fig, axes = plt.subplots(nrows=1, ncols=3, figsize=(8, 8), sharex=True, sharey=True)
    ax = axes.ravel()

    ax[0].imshow(gamma_img, cmap=plt.cm.gray)
    ax[0].set_title("Original")

    ax[1].imshow(img, cmap=plt.cm.nipy_spectral)
    ax[1].set_title("Contours")

    ax[2].imshow(img2, cmap=plt.cm.nipy_spectral)
    ax[2].set_title("Labels")


    for a in ax:
    a.axis('off')

    fig.tight_layout()
    plt.show()


    I indicated the parameters that I am changing as bold.

    Thank you for your interest.

    Continue reading...

Compartilhe esta Página