diff --git a/img5.jpg b/img5.jpg new file mode 100644 index 0000000..6cc61ea Binary files /dev/null and b/img5.jpg differ diff --git a/main.py b/main.py index 8541447..39fbeaf 100644 --- a/main.py +++ b/main.py @@ -24,13 +24,28 @@ def sizeVexScrew(iteml): iteml = round(iteml) iteml /= 8 return iteml - + +def sizeStandoff(iteml): + # Standoff Sizing code + + #print("Thread Length: " + str(iteml)) + iteml *= 4 + iteml = round(iteml) + iteml /= 4 + return iteml + + def larger(a, b): if a >= b: return a else: return b +def smaller(a, b): + if a < b: + return a + else: + return b # construct the argument parse and parse the arguments ap = argparse.ArgumentParser() ap.add_argument("-i", "--image", required=True, @@ -49,12 +64,15 @@ if type(args["number"]) == type(selected): # load the image, convert it to grayscale, and blur it slightly image = cv2.imread(args["image"]) -image = cv2.resize(image, (image.shape[1]*2, image.shape[0]*2), interpolation = cv2.INTER_NEAREST) +image = cv2.resize(image, (int(image.shape[1]*0.2), int(image.shape[0]*0.2)), interpolation = cv2.INTER_NEAREST) if args2.show: - cv2.imshow("Screw Length Detection", image) + cv2.imshow("Item Sorter", image) cv2.waitKey(0) gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) gray = cv2.GaussianBlur(gray, (7, 7), 0) +if args2.show: + cv2.imshow("Item Sorter", gray) + cv2.waitKey(0) # perform edge detection, then perform a dilation + erosion to @@ -62,8 +80,9 @@ gray = cv2.GaussianBlur(gray, (7, 7), 0) edged = cv2.Canny(gray, 50, 100) edged = cv2.dilate(edged, None, iterations=1) edged = cv2.erode(edged, None, iterations=1) + if args2.show: - cv2.imshow("Screw Length Detection", edged) + cv2.imshow("Item Sorter", edged) cv2.waitKey(0) # find contours in the edge map cnts = cv2.findContours(edged.copy(), cv2.RETR_EXTERNAL, @@ -75,6 +94,62 @@ cnts = imutils.grab_contours(cnts) (cnts, _) = contours.sort_contours(cnts) pixelsPerMetric = None num = 0 + + + + + +# Calibration loop +for c in cnts: + # if the contour is not sufficiently large, ignore it + if cv2.contourArea(c) < 100: + continue + # compute the rotated bounding box of the contour + orig = image.copy() + box = cv2.minAreaRect(c) + box = cv2.cv.BoxPoints(box) if imutils.is_cv2() else cv2.boxPoints(box) + box = np.array(box, dtype="int") + box = perspective.order_points(box) + (tl, tr, br, bl) = box + (tltrX, tltrY) = midpoint(tl, tr) + (blbrX, blbrY) = midpoint(bl, br) + (tlblX, tlblY) = midpoint(tl, bl) + (trbrX, trbrY) = midpoint(tr, br) + dA = np.linalg.norm(np.array((tltrX, tltrY, 0)) - np.array((blbrX, blbrY, 0))) + dB = np.linalg.norm(np.array((tlblX, tlblY, 0)) - np.array((trbrX, trbrY, 0))) + area_box = dA * dB + (x,y),radius = cv2.minEnclosingCircle(c) + area_contour = cv2.contourArea(c) + area_circle = math.pi * pow(radius, 2) + boxiness = area_contour / area_box + circleness = area_contour / area_circle + circular = False + rectangular = False + if boxiness > circleness: + rectangular = True + cv2.drawContours(orig, [box.astype("int")], -1, (0, 255, 0), 2) + else: + circular = True + cv2.circle(orig,(int(x),int(y)),int(radius),(0,255,0),2) + + if pixelsPerMetric is None and circular is True: + pixelsPerMetric = smaller(dA, dB) / args["width"] + #cv2.imshow("Screw Length Detection", orig) + #cv2.waitKey(0) + # order the points in the contour such that they appear + # in top-left, top-right, bottom-right, and bottom-left + # order, then draw the outline of the rotated bounding + # box + + #cv2.drawContours(orig, [box.astype("int")], -1, (0, 255, 0), 2) + + + # if the pixels per metric has not been initialized, then + # compute it as the ratio of pixels to supplied metric + # (in this case, inches) + # compute the size of the object + +orig = image.copy() # loop over the contours individually for c in cnts: num += 1 @@ -82,7 +157,7 @@ for c in cnts: if cv2.contourArea(c) < 100: continue # compute the rotated bounding box of the contour - orig = image.copy() + box = cv2.minAreaRect(c) box = cv2.cv.BoxPoints(box) if imutils.is_cv2() else cv2.boxPoints(box) @@ -93,7 +168,6 @@ for c in cnts: # order, then draw the outline of the rotated bounding # box box = perspective.order_points(box) - cv2.drawContours(orig, [box.astype("int")], -1, (0, 255, 0), 2) # loop over the original points and draw them #for (x, y) in box: @@ -118,38 +192,92 @@ for c in cnts: #cv2.circle(orig, (int(trbrX), int(trbrY)), 5, (255, 0, 0), -1) # draw lines between the midpoints - cv2.line(orig, (int(tltrX), int(tltrY)), (int(blbrX), int(blbrY)), - (255, 0, 255), 2) - cv2.line(orig, (int(tlblX), int(tlblY)), (int(trbrX), int(trbrY)), - (255, 0, 255), 2) - # compute the Euclidean distance between the midpoints + # compute the Euclidean distance between the midpoints dA = np.linalg.norm(np.array((tltrX, tltrY, 0)) - np.array((blbrX, blbrY, 0))) dB = np.linalg.norm(np.array((tlblX, tlblY, 0)) - np.array((trbrX, trbrY, 0))) # if the pixels per metric has not been initialized, then # compute it as the ratio of pixels to supplied metric # (in this case, inches) - if pixelsPerMetric is None: - pixelsPerMetric = dB / args["width"] + #if pixelsPerMetric is None: + # pixelsPerMetric = dB / args["width"] # compute the size of the object dimA = dA / pixelsPerMetric dimB = dB / pixelsPerMetric - if num == num: - iteml = larger(dimA, dimB) - print("Screw Length (RAW): " + str(iteml)) - iteml = sizeVexScrew(iteml) - print("Rounded Length: " + str(iteml)) - # draw the object sizes on the image + if num == selected or args2.show: + area_box = dA * dB + (x,y),radius = cv2.minEnclosingCircle(c) + area_contour = cv2.contourArea(c) + area_circle = math.pi * pow(radius, 2) + boxiness = area_contour / area_box + circleness = area_contour / area_circle + circular = False + rectangular = False + if boxiness > circleness: + rectangular = True + cv2.drawContours(orig, [box.astype("int")], -1, (0, 255, 0), 2) + else: + circular = True + cv2.circle(orig,(int(x),int(y)),int(radius),(0,255,0),2) + + + objtype = "Unknown" + itemw = larger(dimA, dimB) + itemwr = itemw + itemwr *= 8 + itemwr = round(itemwr) + itemwr /= 8 + + itemh = smaller(dimA, dimB) + itemhr = itemh + itemhr *= 16 + itemhr = round(itemhr) + itemhr /= 16 + if circular and itemwr == 0.75: + objtype = "Penny" + iteml = 0 + else: + epsilon = 4#0.05*cv2.arcLength(c,True) + #print(str(epsilon)) + approx = cv2.approxPolyDP(c,epsilon,True) + cv2.drawContours(orig, (approx.astype("int")), -1, (255, 0, 0), 8) + if not cv2.isContourConvex(approx): + objtype = "Screw" + iteml = larger(dimA, dimB) + #print("Screw Length (RAW): " + str(iteml)) + iteml = sizeVexScrew(radius * 2 / pixelsPerMetric) + #print("Rounded Length: " + str(iteml)) + else: + if itemhr == 0.3125: + objtype = "Standoff" + iteml = sizeStandoff(radius * 2 / pixelsPerMetric) + if itemhr == 0.1875: + objtype = "Axle" + iteml = radius * 2 / pixelsPerMetric + + print(str(iteml)) + # draw the object sizes on the image if args2.show: - cv2.putText(orig, "{:.5f}in".format(larger(dimA, dimB)), + #cv2.putText(orig, "{:.5f}in".format(itemhr), + # (int(trbrX + 20), int(trbrY)), cv2.FONT_HERSHEY_SIMPLEX, + # 0.65, (255, 255, 255), 2) + cv2.putText(orig, str(objtype), (int(trbrX + 20), int(trbrY)), cv2.FONT_HERSHEY_SIMPLEX, 0.65, (255, 255, 255), 2) - if num > 1: - cv2.putText(orig, "{:.3f}in screw".format(iteml), # print screw length + if objtype == "Screw": + cv2.putText(orig, str(iteml) + "in thread", # print screw length + (int(trbrX + 20), int(trbrY + 20)), cv2.FONT_HERSHEY_SIMPLEX, + 0.65, (255, 255, 255), 2) + if objtype == "Standoff": + cv2.putText(orig, str(iteml) + "in", # print standoff length + (int(trbrX + 20), int(trbrY + 20)), cv2.FONT_HERSHEY_SIMPLEX, + 0.65, (255, 255, 255), 2) + if objtype == "Axle": + cv2.putText(orig, "{:.2f}in".format(iteml), # print axle length (int(trbrX + 20), int(trbrY + 20)), cv2.FONT_HERSHEY_SIMPLEX, 0.65, (255, 255, 255), 2) # show the output image - cv2.imshow("Screw Length Detection", orig) + cv2.imshow("Item Sorter", orig) cv2.waitKey(0) \ No newline at end of file