Reputation: 41
I'm trying to segment each charm item in this collective image.
The shapes are irregular and inconsistent:
https://i.imgur.com/sf8nOau.jpg
I have another image where there is some consistency with the top row of items, but ideally I'd be able to process and brake up all items in one go:
http://i.imgur.com/WiiYBay.jpg
I have no experience with opencv so I'm just looking for best possible tool or approach to take. I've read about background subtraction as well as color clustering, but I'm not sure about those either.
Any ideas on how to best approach this? Thanks.
Upvotes: 1
Views: 1291
Reputation: 1516
import cv2
import numpy as np
im=cv2.imread('so1.jpg')
gray = cv2.cvtColor(im,cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray,0,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)
kernel = np.ones((3,3),np.uint8)
res = cv2.dilate(thresh,kernel,iterations = 1)
res = cv2.erode(res,kernel,iterations = 1)
res = cv2.dilate(res,kernel,iterations = 1)
cv2.imshow('thresh',res)
_,contours, hierarchy = cv2.findContours(res.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
for cnt in contours:
x,y,w,h = cv2.boundingRect(cnt)
cv2.rectangle(im,(x,y),(x+w,y+h),(0,255,0),2)
cv2.imshow('image',im)
cv2.waitKey(0)
cv2.destroyAllWindows()
Now having the contours you can crop them out
import cv2
import numpy as np
im=cv2.imread('so.jpg')
gray = cv2.cvtColor(im,cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray,0,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)
kernel = np.ones((3,3),np.uint8)
res = cv2.dilate(thresh,kernel,iterations = 1)
res = cv2.erode(res,kernel,iterations = 1)
res = cv2.dilate(res,kernel,iterations = 8)
cv2.imshow('thresh',res)
_,contours, hierarchy = cv2.findContours(res.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
count=0
for cnt in contours:
blank=np.zeros(im.shape,dtype=np.uint8)
x,y,w,h = cv2.boundingRect(cnt)
epsilon = 0.001*cv2.arcLength(cnt,True)
approx = cv2.approxPolyDP(cnt,epsilon,True)
cv2.fillConvexPoly(blank,approx,(255, 255, 255))
masked_image = cv2.bitwise_and(im, blank)
cv2.imwrite('results_so/im'+str(count)+'.jpg',masked_image[y:y+h,x:x+w])
count+=1
cv2.imshow('image',im)
cv2.waitKey(0)
cv2.destroyAllWindows()
Some small noises are also detected as objects you can eliminate those by only taking contours whose area is greater than a certain value .
Upvotes: 3