Best way to separate rock fragments in image

Viewed 1016

I'm trying to make a program to calculate the size distribution of rock fragments based on images from a conveyor belt. I can only achieve that by image segmentation and labeling. Unfortunately, my results are not satisfactory because the program has a problem with dark spots on rock fragments. These spots are incorrectly recognized as edges of the fragments (e.g in the left top corner program found a lot of small fragments, where in reality this is just one big fragment. Did anyone deal with a problem like that?

What I tried until now:

  • Canny edge detector
  • thresholding with various parameters
  • findContours in opencv
  • sharpening / bilateral filtering
  • meijering, sato, frangi, hessian ridge detectors from skimage.filters - I'm not sure if I used them in a proper way - maybe someone has more experience with these and know how to find parameters that would fit.
  • opening/closing (dilate, erode) with different kernels
  • current approach: opening -> finding background area -> finding foreground area -> subtracting background and foreground area -> watershed.

code for the current approach:


import numpy as np
import cv2
from skimage import data, util, filters, color, measure
from skimage.segmentation import watershed, clear_border
import matplotlib.pyplot as plt
from skimage import img_as_ubyte


name = 'cut.png'
img = cv2.imread(name, 0)
img_color_org = cv2.imread(name)

ret, thresh = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)
kernel2 = np.ones((2, 2), np.uint8)
kernel3 = np.ones((3, 3), np.uint8)

opening = cv2.morphologyEx(
    thresh, cv2.MORPH_OPEN, kernel2, iterations=1)

sure_bg = cv2.dilate(opening, kernel3, iterations=3)

dist_transform = cv2.distanceTransform(opening, cv2.DIST_L2, 3)

ret2, sure_fg = cv2.threshold(
    dist_transform, 0.15*dist_transform.max(), 255, 0)
sure_fg = np.uint8(sure_fg)

unknown = cv2.subtract(sure_bg, sure_fg)

ret3, markers = cv2.connectedComponents(sure_fg)
markers = markers + 10
markers[unknown == 255] = 0
markers = cv2.watershed(img_color_org, markers)
img_color_org[markers == -1] = [0, 0, 255]

img2 = color.label2rgb(markers, bg_label=0)
cv2.imwrite('img.png', img_color_org)
cv2.waitKey(0)

pure imageOriginal Image

before watershed Image after background subtraction, and before watershed operation

current algorithm segmentation Watershed applied to the original image

hand-made Segmentation in paint hand-made segmentation with desired edges

Original image with better qualityOriginal image with better quality

Any help will be greatly appreciated!

0 Answers
Related