I am looking for a way to detect if there are secondary objects in an image or if the image just has the one main object. I've done a bit of research, but I haven't been able to find anything quite like what I am looking for.
An example image would be:
The main object being the two detergent bottles since they overlap and the secondary object would be the "2 pack" pop up bubble in the top right. I would expect this image to return something like: "This image has secondary objects" or a count of the objects.
Here is one way to do that in Python/OpenCV
Input:
import cv2
import numpy as np
# read image
img = cv2.imread("tide.jpg")
# convert img to grayscale
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# invert gray image
gray = 255 - gray
# threshold gray image
#thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY)[1]
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)[1]
# apply morphology close
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
morph = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)
# Get contours
cntrs = cv2.findContours(morph, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cntrs = cntrs[0] if len(cntrs) == 2 else cntrs[1]
result = img.copy()
for c in cntrs:
cv2.drawContours(result, [c], -1, (0,0,255), 1)
count = len(cntrs)
print("")
print("count =",count)
print("")
if count > 1:
print("This image has secondary objects")
else:
print("This image has primary object only")
# write results to disk
cv2.imwrite("tide_thresh.png", thresh)
cv2.imwrite("tide_morph.png", morph)
cv2.imwrite("tide_object_contours.png", result)
# display it
cv2.imshow("thresh", thresh)
cv2.imshow("morph", morph)
cv2.imshow("result", result)
cv2.waitKey(0)
Thresholded image:
Morphology close image:
Contours on image:
Count of contours and messages:
count = 2
This image has secondary objects
Following @fmw42's advice, I did a bit of research and found a script that worked well after a little bit of tinkering:
import cv2
import numpy as np
import sys
img = cv2.imread(sys.argv[1], cv2.IMREAD_UNCHANGED)
#convert img to grey
img_grey = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
#set a thresh
thresh = 230
#get threshold image
ret,thresh_img = cv2.threshold(img_grey, thresh, 255, cv2.THRESH_BINARY_INV)
#find contours
contours, hierarchy = cv2.findContours(thresh_img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
#create an empty image for contours
# img_contours = np.zeros(img.shape)
img_contours = np.zeros_like(img)
# draw the contours on the empty image
cv2.drawContours(img_contours, contours, -1, 255, 3)
#save image
cv2.imshow('contours',img_contours)
# Wait indefinitely until you push a key. Once you do, close the windows
print len(contours)
cv2.waitKey(0)
cv2.destroyAllWindows()
My main issue was the threshold setting and I found that 230 worked best with my sample images, although it still is not perfect. I'm hoping there is a better way or something I can add to this.
this image returned 1 as expected, but my initial test image returns 3 at this threshold setting when I would expect 2. At 200 thresh it returns 2, but I was willing to compromise because the main thing I need to know is if it is more than 1.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.