shark38j
shark38j

Reputation: 124

Opencv Binary Item Detection

I am working on a program to find debris that get stuck in parts that I make. So far I have been able to take a clean part and a part with a chip in it and subtract the two images, leaving any difference between the two as a binary image. What I don't understand is how to detect this item in the binary image. So far I used the SimpleBlobDetector function, but I have to blur the image so much to get it to work that I'm concerned it won't work with smaller debris. I want to be able to detect the original without extensive blurring. Any help would be appreciated. Code and images are below.

import cv2
import numpy as np

#Load Images
tempImg = cv2.imread('images/partchip.jpg')
lineImg = cv2.imread('images/partnochip.jpg')

#Crop Images
cropTemp = tempImg[460:589, 647:875]
cropLine = lineImg[460:589, 647:875]

#Gray Scale
grayTemp = cv2.cvtColor(cropTemp,cv2.COLOR_BGR2GRAY)
grayLine = cv2.cvtColor(cropLine,cv2.COLOR_BGR2GRAY)

#Subtract Images
holder = cv2.absdiff(grayTemp,grayLine)

#THreshold Subtracted Image
th, imgDiff = cv2.threshold(holder, 160, 255, cv2.THRESH_BINARY_INV)

#Blur Image
#blur = imgDiff
blur = cv2.blur(imgDiff,(20,20))

#Detect Blobs
detector = cv2.SimpleBlobDetector_create()
blob = detector.detect(blur)


imgkeypoints = cv2.drawKeypoints(blur, blob, np.array([]), (0,255,0),  cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
originalWithPoints=cv2.drawKeypoints(cropTemp, blob, np.array([]), (0,255,0),  cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)

cv2.namedWindow("Template", cv2.WINDOW_NORMAL)
cv2.namedWindow("Line", cv2.WINDOW_NORMAL)
cv2.namedWindow("Difference", cv2.WINDOW_NORMAL)

cv2.resizeWindow("Template", 500, 300)
cv2.resizeWindow("Line", 500, 300)
cv2.resizeWindow("Difference", 500, 300)


cv2.imshow('Template',originalWithPoints)
cv2.imshow('Line',cropLine)
cv2.imshow('Difference',imgkeypoints)


cv2.waitKey(0)
cv2.destroyAllWindows()

Part with chip Part with No Chip

Upvotes: 0

Views: 472

Answers (1)

Jeru Luke
Jeru Luke

Reputation: 21233

I used your code to find the anomaly. I obtained contour having the greatest area on the imgDiff binary image. Using that I was able to bound it with a rectangle.

enter image description here

I hope this is what you are looking for....

EDIT:

I have explained the procedure along with code below:

Note: Invert your imgDiff using cv2.bitwise_not(imgDiff), because contours are found if objects are in white.

#---Finding the contours present in 'imgDiff'---
_, contours,hierarchy = cv2.findContours(imgDiff,2,1)

ff = 0   #----to determine which contour to select---
area = 0   #----to determine the maximum area---
for i in range(len(contours)):
    if(cv2.contourArea(contours[i]) > area):
        area = cv2.contourArea(contours[i])
        ff = i

#---Bounding the contour having largest area---
x,y,w,h = cv2.boundingRect(contours[ff])
cv2.rectangle(img,(x,y),(x+w,y+h),(0,255,0),2)
cv2.imshow('fin.jpg',img)

Upvotes: 1

Related Questions