How to detect bullet holes on a shooting target - python

I'm currently working on my first assignment in image processing (using OpenCV in Python, but I'm open to any libraries and languages). My assignment is to calculate a precise score (to tenths of point) of one to several shooting holes in an image uploaded by a user. The issue is that the image uploaded by the user can be taken on different backgrounds (although it will never match the rest of the target mean colors). Due to this, I have ruled out most of the solutions found on the internet and most of the solutions I could come up with.
Summary of my problem
Bullet holes identification:
bullet holes can be on different backgrounds
bullet holes can overlap
single bullet holes will always be of similar size (there is only one type of caliber used on all of the calculated shooting targets)
I'm able to calculate a very precise radius of the shooting hole
Shooting targets:
there are two types of shooting targets that my app is going to calculate (images provided below)
photos of the shooting targets can be taken in different lighting conditions
Shooting target 1 example:
Shooting target 2 example:
Shooting target examples to find bullet holes in:
shooting target example 1
shooting target example 2
shooting target example 3
shooting target example 4
shooting target example 5
What I tried so far:
Color segmentation
due to the reasons mentioned above
Difference matching
to be able to actually compare the target images (empty and fired on), I have written an algorithm that crops the target by its outer largest circle (its radius + bullet size in pixels)
after that, I have probably tried all of the ways of images comparison found on the internet
for example: brute force matching, histogram comparisons, feature matching and many more
I failed here mostly because the colors on both compared images were a bit different and also because one of the images was sometimes taken in a slight angle and therefore the circles weren't overlapping and they were calculated as differences
Hough circles algorithm
since I know the radius (in pixels) of the shots on the target I thought I could simply detect them using this algorithm
after several hours/days of playing with parameters of HoughCircles function, I figured it would never work on all of the uploaded images without changing the parameters based on the uploaded image
Edge detection and finding contours of the bullet holes
I have tried two edge detection methods (Canny and Sobel) while playing with image smoothening algorithms (like blurring, bilateral filtering, metamorphization, etc..)
after that, I have tried to find all of the contours in the edge detected image and filter out the circles of the target with a similar center point
this seemed like the solution at first, but on several test images it wouldn't work properly :/
At this point, I have ran out of ideas and therefore came here for any kind of advice or an idea that would push me further. Is it possible that there simply isn't a solution to such complicated shooting target recognition or am I just too inexperienced to come up with it?
Thank you in advance for any help.
Edit: I know I could simply put a single color paper behind the shooting target and find the bullets that way. This is not how I want the app to work thought and therefore it's not a valid solution to my problem.

Related

How to distinguish two shooting targets between each other using OpenCV

Let me start by saying that I'm a complete amateur in image recognition and I'm trying to complete my first assignment using OpenCV in Python. I'm currently really struggling and therefore I came here for some advice or any help in general that would put me on the right path.
What am I currently trying to do:
My goal here is to recognize a shooting target image that user uploads and compare it to one of two shooting target templates (images provided lower). My app is afterward going to calculate this shooting target based on the template it matches and give the user a really accurate score of his shot/shots (based on millimeters from the center of the target). This is just a long goal. For now, I'm just trying to figure out how to distinguish the uploaded target image from the templates I have.
Examples of shooting targets:
As I mentioned I have two shooting target templates: target 1 and target 2.
The user then uploads a target that must match one of the templates.
Example that matches target 1
Example that matches target 2
Whenever the uploaded shooting target doesn't match any of the templates, the app should tell the user and not continue with the calculation.
What have I done and tried so far:
For starters, I figured it would be beneficial to remove everything from the background and crop the image by the shooting target, and so I did. (I thought if I removed all of the background interference I could easily just compare the two images, but I later found out this actually wouldn't be accurate at all).
After that, I tried to calculate the percentage of the black color to the other color inside the target (without the background), but again found out this wouldn't be accurate since the shooter could shoot through a lot of the black color and then the percentage would fluctuate. Also, I wouldn't be able to tell if it's one of the templates since another completely different shooting target could have the same amount of black color in the middle.
As of comparison of the two images, I tried a lot of ways (histogram, feature matching with brute force, template matching) and neither of those seemed to be accurate nor usable (I could have been doing it wrong tho, that's a possibility).
What I have figured after all of those failures is that possibly the best solution would be to compare the circles inside the shooting target or the numbers inside the black middle circles, but I couldn't figure out how to do so properly.
Do you guys have any idea on how to go about this? I would really appreciate any help or any push towards the solution of my problem. Code examples are highly appreciated and would make my day.
Best regards.
The targets seem to differ only in score bands (rings) 4, 5 and 6. So I would try and concentrate on those areas.
I took your sample images and resized them to exactly 500x500 pixels, then I measured the radius from the centre to the outside edge of band 4 (which was 167 px) and to the edge of band 6 (which was 95 px). So the outer limit of the area of interest is 167/500, or 0.33xW and the inner limit is 95/500, or 0.19xW where W is the width of the enclosing rectangle.
So, you can draw that mask like this:
#!/usr/bin/env python3
import numpy as np
import cv2
# Define width/height of target in pixels
W = 300
# Make mask, white for area of interest, black elsewhere
mask = np.zeros((W,W),dtype=np.uint8)
cv2.circle(mask, (W//2,W//2), int(0.33*W), 255, -1) # White outer circle
cv2.circle(mask, (W//2,W//2), int(0.19*W), 0, -1) # Black inner circle
That gives you this mask:
You can now calculate, say, the mean of all pixels within that mask using:
maskedMean = cv2.mean(YourImage, mask)
and only pixels that are white within the mask will contribute to the mean.
Here is the mask placed beside one of your targets:

How to detect the relative depth of pixels on a image?

I am trying to obtain the relative depth of pixels of an image. For example, the image in https://www.awn.com/news/nvidia-unveils-quadro-rtx-worlds-first-ray-tracing-gpu . I don't need the precise distance of each pixel, which I believe would be impossible, but I would like to get something as "the green ball is further than the other balls". Is it possible using OpenCV in python? The codes I generated can identify each ball, but not their relative distance or depth, so they are pretty much useless to my intents.
That's an ill-posed problem (you can not measure depth with a single RGB camera) and a topic of resent research. I found this survey paper. Most often a depth image is learned from an RGB image using convolutional neural networks.
However, if you use a lot of prior information about your scene (all objects are circular within in the image and the partially visible circles corresponds to the ones which are in the background), then you might be able to do something with heuristical methods like, thresholding, edge detection or hough transforms, but it won't be easy.

Best OpenCV algorithm for detecting fast moving ball?

I am new to OpenCV. I am working on a project that involves tracking and detecting a spinning roulette ball. Here is the video I want to use: https://www.youtube.com/watch?v=IzZNaVQ3FnA&list=LL_a67IPXKsmu48W4swCQpMQ&index=7&t=0s
I want to get the ball time for 1 revolution. But the ball is quite fast and hard to detect. I am not sure how to overcome this.
What would be the best algorithm for doing this?
By subtracting successive images, you will isolate the ball as a (slightly curved) line segment. Both its length and its angular position are cues for the speed.
Anyway, these parameters are a little tricky to extract for a side view, as the ellipse has to be "unprojected" to a top view, to see the original circle. You need to know the relative position of the wheel and the viewer, which you most probably don't know.
An approximate solution is obtained by stretching the ellipse in the direction of the small axis.

Opencv identify difference between similar object

I am working on a project to figure out the difference between two objects and tag them with the proper model code.
I need help with a suggestion on how can we tackle such problem with image processing using OpenCV, following are the images
Till now I tried calculating black pixel difference between two images after doing binary threshold and also calculated a number of holes present on the gasket.
I also tried using feature points but it didn't worked well
what else can be done to improve the detection?
Thank you
The holes are excellent features that can be robustly detected by blob analysis.
In the first place, locate the large circle and determine its center and radius. The radius might be a first discriminant feature.
Next, establish the configuration of the screw holes around the center. You can use the distance to the center, the number of holes and the angles they define around the center.
If this is still not enough, you can register the gaskets and compare them to the models by matching the screw holes, adjusting the rotation, then comparing pixel-wise with a similarity measure such as SAD or SSD.

Using real time video feed to monitor analog gauge in Python

I'm hoping someone here can help me go about trying to solve this problem. I'm trying to figure out a good way to use a real time video feed to run a python 0script when a pressure gauge that looks like this reaches a certain variable pressure.
I'm pretty confident that this shouldn't be too difficult as the gauge will be mounted in a fixed position in the image frame, but am new to this sort of stuff and really don't know where to start.
Any suggestions? Thanks in advance!
This problem could be much tougher than you think. Typically, people use OpenCV for image processing/pattern recognition problems. There are many excellent tutorials for Python available in the documentation
At it's core, your problem is the figure out the angle of rotation of the needle. Then from there, you can calculate what the pressure is. If you're lucky, you can find the needle using Feature Detection + Homography and then calculate the angle. But I have my doubts that this kind of image leads itself to feature detection.
Template Matching will be able to find the needle, but it's very sensitive to rotation, so you'd have to generate a large number of templates with different needle angles and then go through all of your templates every time you want a pressure reading.
It may well be faster, cheaper, and easier to use an electronic pressure gauge for reading pressure. There are any number of ways you can get the output of your electronic gauge into Python. Some gauges can be connected to the network. Some can communicate as a serial port with RS232/422 or USB.
If you can find a gauge with a digital display, it should be more straighforward to do some kind of OCR/Template Matching to read the display from a camera.
Edit:
#jeremy arsenault's comment prompted me to think of another solution. If you are focused mostly on detecting when the needle crosses a threshold, you could look for the leading edge of the dial. And you could look more towards the center of the dial, where there are no indicators.
This kind of image really lends itself to easy conversion to Thresholding to black and white. The dial is black and the background (at least towards the center) is white. After you do some Morphology and Thresholding of your image, you could look for black pixels of the dial. No template matching required. Pictures below illustrate some of the ideas. The first picture is your image thresholded to black and white. The starting image was very clean, but if you're grabbing from a camera, you'll probably have to do some Blurring, Morphology before thresholding to get no stray black pixels where you don't want them. The second image has a superimposed circle where you can look for black pixels. You can find the leading edge and trailing edge and average to get a fairly precise value of the center.
Some more implementation details/pseudocode. For computer images, origin is usually top left corner and +y goes down. Also, I've defined increasing angle theta with increasing pressure. Parametric equation for circle is
x = x0 - r*cos(theta + theta0)
y = y0 - r*sin(theta + theta0)
theta0 is the offset angle that gives zero pressure (around -45 degrees for gauge pictured. The brute force way to look for the needle would be to start sweeping the angle from zero and increasing until you find a black pixel at x,y. Then keep increasing until you find a white pixel at x,y. The average of the two angles gives you the center of the needle and you should be able to calculate pressure.

Categories

Resources