Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
186 views
in Technique[技术] by (71.8m points)

python - Count glass pieces with OpenCV

I'm trying to count the number of pieces a glass broke into, using OpenCV (cv2 / Python).

One input example is this image: enter image description here

Following the tutorial I found here, I identified a sure foreground and background and then used the Watershed algorithm.

I got this result:

enter image description here

As you can see, the solution is not perfect: Some pieces are split into two, some are merged with others. Also the long lines that should be ignored are seen as borders sometimes.

Do you have different ideas for techniques I could use? I'm pretty new to OpenCV.

Thanks! :)


EDIT: Here's my code because commenters asked for it. As I said, it follows the posted link.

import cv2
import matplotlib.pyplot as plt
import numpy as np
import sys
%matplotlib inline

# Default show images in greyscale
plt.gray()

img = cv2.imread('../data/raw/example.jpg',0)

# noise removal
img = cv2.GaussianBlur(img, (5, 5), 0)
ret, thresh = cv2.threshold(img,0,255,cv2.THRESH_OTSU)
kernel = np.ones((3,3),np.uint8)
opening = cv2.morphologyEx(thresh,cv2.MORPH_OPEN,kernel, iterations = 2) 

# sure background area
sure_bg = cv2.dilate(opening,kernel,iterations=1)

# Finding sure foreground area
dist_transform = cv2.distanceTransform(opening,cv2.DIST_L2,5)
ret, sure_fg = cv2.threshold(dist_transform,0.4*dist_transform.max(),255,0)

# Finding unknown region
sure_fg = np.uint8(sure_fg)
unknown = cv2.subtract(sure_bg,sure_fg)

# Marker labelling
ret, markers = cv2.connectedComponents(sure_fg)

# Add one to all labels so that sure background is not 0, but 1
markers = markers+1

# Now, mark the region of unknown with zero
markers[unknown==255] = 0

# Watershed
img_color = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
markers = cv2.watershed(img_color,markers)
img_color[markers == -1] = [255,0,0]

def plot_image(image, figsize=(18,18)):
    fig, ax = plt.subplots(figsize=(18, 20))
    ax.imshow(image, cmap='gray')
    plt.show()

plot_image(img_color)

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Result

import numpy as np
import matplotlib.pyplot as plt
import cv2
from skimage.measure import label

# Read Image
img = cv2.imread('1.jpg', 0)
# Detect Edges
sobelx = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=5)
sobely = cv2.Sobel(img,cv2.CV_64F,0,1,ksize=5)
sobel = np.sqrt(sobelx**2 + sobely**2)
# Normalize and Invert
sobel = 255 - (255*sobel/(sobel.max()-sobel.min())).astype(np.uint8)
# Noise Filtering
median = cv2.medianBlur(sobel,5)
median = cv2.medianBlur(sobel,7)
# Thresholding
median[median<233] = 0
median[median>=233] = 255
# Labelling
lab = label(median) 

# Visualizing the results
plt.figure(num="Count is: {}".format(len(np.unique(lab))-1)) # -1 because of the black area outside the image

plt.subplot(221)
plt.imshow(img, cmap='gray')
plt.title('Original')
plt.axis('off')

plt.subplot(222)
plt.imshow(median, cmap='gray')
plt.title('filtered')
plt.axis('off')

plt.subplot(223)
plt.imshow(sobel, cmap='gray')
plt.title('Edges')
plt.axis('off')

plt.subplot(224)
plt.imshow(lab, cmap='gray')
plt.title('Labelled')
plt.axis('off')

plt.show()

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...