Distinguish head of bolt and its thread

asked 2020-09-17 17:10:17 -0500

killerpiraat gravatar image

updated 2020-09-18 01:32:20 -0500

berak gravatar image

Hello. Im working on a project where i want to identify different kind of bolts. I made it so far that i can find the contours, place rectangs, and identify the reference (for the dimensions) in the picture. Because i am not interested in the head of the bolt, but only in the length and width of the threaded part, i need to remove the bold. De bolts can be placed in a random position, so i thought, take a crop of each bolt in the picture (there can be multiple bolts in 1 picture), rotate it so that its horizontal and count the pixels. But if you have other ideas i like to hear them. This method is a littly buggy if you ask me, but worth a try. Im not having succes cropping each bolt into a new image

Here what i got so far:

image description

import numpy as np
import cv2

image = cv2.imread("knipsel5.jpg")
output = image.copy()

scalePercent = 100
width = int(image.shape[1] * scalePercent / 100)
height = int(image.shape[0] * scalePercent / 100)
dim = (width, height)
resizedImage  = cv2.resize(image, dim, interpolation = cv2.INTER_AREA)

blurred_image = cv2.GaussianBlur(resizedImage, (5,5), 0)

gray = cv2.cvtColor(blurred_image, cv2.COLOR_BGR2GRAY)
_, threshold = cv2.threshold(gray, 100, 255, cv2.THRESH_BINARY_INV)


circles = cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, 1.2, 100)

if circles is not None:
    circles = np.round(circles[0, :]).astype("int")

    for(x,y,r) in circles:
        cv2.circle(resizedImage, (x, y), r, (0, 255, 0), 4)
    print("X coord:")
    print("Y coord:")

    diameter = r*2
    reference = 23/123

    cv2.putText(resizedImage, ("coin "), ((x+100), (y-100)), font, 1, (0))
    #cv2.putText(resizedImage, (r), ((x+120), (y-100)), font, 1, (0))

    #cv2.imshow("output", np.hstack([image, resizedImage]))

    circle = cv2.circle(threshold, (x,y), (r+50), (0,0,0), -1)
    print("no dimension reference found")

contours, hierarchy = cv2.findContours(threshold, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
height, width  = threshold.shape
min_x, min_y = width, height
max_x = max_y = 0;

for cnt in contours: 
    approx = cv2.approxPolyDP(cnt, 0.005*cv2.arcLength(cnt, True), True)
    cv2.drawContours(resizedImage, [approx] , 0, (255,0,0), 2)  

    (x,y,w,h) = cv2.boundingRect(approx)
    min_x, max_x = min(x, min_x), max(x+w, max_x)
    min_y, max_y = min(y, min_y), max(y+h, max_y)
    if w > 40 and h > 40:
        cv2.rectangle(resizedImage, (x,y), (x+w,y+h), (255, 0, 0), 2)

    rect = cv2.minAreaRect(approx)
    box = cv2.boxPoints(rect)
    box = np.int0(box)
    cv2.drawContours(resizedImage, [box],0,(0,0,255),2)

    #rectangg = np.array([
    #    [[box[0][0], box[0][1]]],
    #    [[box[1][0], box[1][1]]],
    #    [[box[2][0], box[2][1]]],
    #    [[box[3][0], box[3][1]]],
    #    ])

    lengte = int(rect[1][0])
    breedte = int(rect[1][1])


    print("lengte: ", lengte)
    print("breedte: ", breedte)

    x = approx.ravel()[0]
    y = approx.ravel ...
edit retag flag offensive close merge delete



since you already have a RotatedRect (nice !), you could use its angle property to warp it into a plain horizontal position. then maybe a simple absdiff with a resized template screw. or sum up along the y axis using reduce() to get a "spatial histogram" (along the x axis), easy to find the bolt then

berak gravatar imageberak ( 2020-09-20 06:55:39 -0500 )edit