[Python] better way to find bullet holes in a target

Discussão em 'Python' iniciado por Stack, Abril 5, 2025.

  1. Stack

    Stack Membro Participativo

    Hi I'm making a project about detecting bullet holes in target circles. My original idea was to use Hough circle algorithms to detect both targets which works quite alright for photos that are straight in front of it and bullet holes that are not as good. Sooo I was wandering if anyone could tip me with some better solution on finding them or helping me improve this code.

    import cv2 as cv
    import numpy as np
    import math
    import sys
    from PIL import Image
    import matplotlib.pyplot as plt

    MAX_POINTS = 10

    def main(argv):

    default_file = 'tarczamala.jpg'
    default_size = 600, 600

    im = Image.open(default_file)
    im = im.resize(default_size, Image.ANTIALIAS)
    im.save('600' + default_file)

    filename = argv[0] if len(argv) > 0 else '600' + default_file
    # Loads an image
    src = cv.imread(cv.samples.findFile(filename), cv.IMREAD_COLOR)
    # Check if image is loaded fine
    if src is None:
    print ('Error opening image!')
    print ('Usage: hough_circle.py [image_name -- default ' + default_file + '] \n')
    return -1

    # skala szarości
    gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
    cv.imshow('gray', gray)

    # Bilateral
    bilateral = cv.bilateralFilter(gray, 7, 15, 10)
    cv.imshow('bilateral', bilateral)

    blank = np.zeros(bilateral.shape[:2], dtype='uint8')
    cv.imshow('blank', blank)

    # mask = cv.circle(blank, (bilateral.shape[1] // 2, bilateral.shape[0] // 2), 320, 255, -1)
    # cv.imshow('Mask', mask)
    #
    # masked = cv.bitwise_and(bilateral, bilateral, mask=mask)
    # cv.imshow('masked', masked)

    # Edge Cascade
    canny = cv.Canny(bilateral, 50, 175)
    cv.imshow('canny1', canny)

    # ret, tresh = cv.threshold(gray, 125, 255, cv.THRESH_BINARY)
    # cv.imshow('tresch', tresh)

    contours, hierarchies = cv.findContours(canny, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_NONE)
    print(f'{len(contours)} contour(s) found')

    # cv.drawContours(blank, contours, -1, (255,0,0), 1)
    # cv.imshow('contours drawn', blank)

    rows = canny.shape[0]

    # Target

    circles = cv.HoughCircles(canny, cv.HOUGH_GRADIENT, 1, 0.01,
    param1=100, param2=50,
    minRadius=7, maxRadius=300)

    # print(f'{circles}"')

    biggestCircle = findBiggestCircle(circles)
    # print(f'{biggestCircle} biggest circle')

    mask = cv.circle(blank, (math.floor(biggestCircle[0]), math.floor(biggestCircle[1])), math.floor(biggestCircle[2]), 255, -1)
    cv.imshow('rysowanie granicy', mask)

    masked = cv.bitwise_and(bilateral, bilateral, mask=mask)
    cv.imshow('granice', masked)

    # Edge Cascade
    canny = cv.Canny(masked, 50, 175)
    cv.imshow('canny2', canny)

    if biggestCircle is not None:
    circles = np.uint16(np.around(circles))

    # print(f'{biggestCircle} biggest circle')

    delta_r = biggestCircle[2] / 10
    biggest_circle_center = [biggestCircle[0], biggestCircle[1]]

    center = (math.floor(biggestCircle[0]), math.floor(biggestCircle[1]))
    # print(f'{center} center')
    # circle center
    cv.circle(src, center, 1, (255, 0, 0), 3)
    # circle outline
    radius = math.floor(biggestCircle[2])
    cv.circle(src, center, radius, (0, 0, 255), 3)



    # bullet holes

    hits = cv.HoughCircles(canny, cv.HOUGH_GRADIENT, 1, 10,
    param1=300, param2=10,
    minRadius=7, maxRadius=10)
    # print(f'{hits}"')

    score = countHitScore(hits.tolist(), delta_r, biggest_circle_center)

    print(f'The score is: {score}"')

    if hits is not None:
    hits = np.uint16(np.around(hits))
    for i in hits[0, :]:
    # print(f'promien trafienia {i[2]}"')
    center = (i[0], i[1])
    # circle center
    cv.circle(src, center, 1, (0, 100, 100), 3)
    # circle outline
    radius = i[2]
    cv.circle(src, center, radius, (255, 0, 255), 3)

    cv.imshow("detected circles", src)
    cv.waitKey(0)

    return 0

    def findBiggestCircle(circles):

    # print(f'{circles}')
    listOfCircles = circles[0]
    biggestCircle = listOfCircles[0]

    for circle in listOfCircles:
    # print(f'{circle} circle')
    # print(f'2 {circle}')
    # print(f'3 {biggestCircle}')
    if circle[2] > biggestCircle[2]:
    # print('4')
    biggestCircle = circle
    print(biggestCircle)
    return biggestCircle.tolist()

    def countHitScore(hits, delta_r, target_center):
    score = 0
    print(f'{hits} hits')

    for hit in hits[0]:
    # print(f'{hit} hit')
    # print(f'{(target_center)} center')
    x_dist = hit[0] - target_center[0] if hit[0] > target_center[0] else target_center[0] - hit[0]
    y_dist = hit[1] - target_center[1] if hit[1] > target_center[1] else target_center[1] - hit[1]

    total_dist = math.hypot(x_dist, y_dist) - hit[2]

    punkty = math.ceil(total_dist / delta_r)

    if punkty < 1:
    punkty = 1

    score += 11 - punkty

    # print(f'{total_dist / delta_r} math')
    # print(f'{total_dist / delta_r} total_dist / delta_r')
    print(f'{11 - punkty} zdobyte punkty')
    # print(f'{x_dist} x {y_dist} y')

    return score

    if __name__ == "__main__":
    main(sys.argv[1:])


    [​IMG]

    [​IMG]

    [​IMG]

    Continue reading...

Compartilhe esta Página