How to distinguish two shooting targets between each other using OpenCV - python

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:

Related

How to detect bullet holes on a shooting target

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.

How to detect edge of object using OpenCV

I am trying to use OpenCV to measure size of filament ( that plastic material used for 3D printing)
What I am trying to do is measuring filament size ( that plastic material used for 3D printing ). The idea is that I use led panel to illuminate filament, then take image with camera, preprocess the image, apply edge detections and calculate it's size. Most filaments are fine made of one colour which is easy to preprocess and get fine results.
The problem comes with transparent filament. I am not able to get useful results. I would like to ask for a little help, or if someone could push me the right directions. I have already tried cropping the image to heigh that is a bit higher than filament, and width just a few pixels and calculating size using number of pixels in those images, but this did not work very well. So now I am here and trying to do it with edge detections
works well for filaments of single colour
not working for transparent filament
Code below is working just fine for common filaments, the problem is when I try to use it for transparent filament. I have tried adjusting tresholds for Canny function. I have tried different colour-spaces. But I am not able to get the results.
Images that may help to understand:
https://imgur.com/gallery/CIv7fxY
image = cv.imread("../images/img_fil_2.PNG") # load image
gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY) # convert image to grayscale
edges = cv.Canny(gray, 100, 200) # detect edges of image
You can use the assumption that the images are taken under the same conditions.
Your main problem is that the reflections in the transparent filament are detected as edges. But, since the image is relatively simple, without any other edges, you can simply take the upper and the lower edge, and measure the distance between them.
A simple way of doing this is to take 2 vertical lines (e.g. image sides), find the edges that intersect the line (basically traverse a column in the image and find edge pixels), and connect the highest and the lowest points to form the edges of the filament. This also removes the curvature in the filament, which I assume is not needed for your application.
You might want to use 3 or 4 vertical lines, for robustness.

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.

Homography of soccer field

Okay so i am trying to find homography of a soccer match. What i have till now is
Read images from a folder which is basically many cropped images of a template soccer field. Basically this has images for center circle and penalty lines etc.
Read video stream from a file and crop it into many smaller segments.
Loop inside the images in video stream and inside that another loop for images that i read from folder.
Now in the two images that i get through iteration , i applied a green filter because of my assumption that field is green
Use orb to find points and then find matches.
Now the Problem is that because of players and some noise from croud, i am unable to find proper matches for homography. Also removing them is a problem because that also tends to hide the soccer field lines that i need to calculate the homography on.
Any suggestions on this is greatly appreciated. Also below are some sample code and images that i am using.
"Code being used"
Sample images
Output that i am getting
The image on right of output is a frame from video and that on left is the same sample image that i uploaded after filterGreen function as can be seen from the code.
Finally what i want is for the image to properly map to center circle so i can draw a cube in center, Somewhat similar to "This example" . Thanks in advance for helping me out.
An interesting technique to throw at this problem is RASL. It computes homographies that align stacks of related images. It does not require that you specify corresponding points on the images, but operates directly on the image pixels. It is robust against image occlusions (eg, players moving in the foreground).
I've just released a Python implementation here: https://github.com/welch/rasl
(there are also links there to the original RASL paper, MATLAB implementation, and data).
I am unsure if you'd want to crop the input images to that center circle, or if the entire frames can be aligned. Try both and see.

How can I detect a grid of filled circles?

Given an image of a connect-4 board I'd like to recognize and output the board's state (a 6 by 7 matrix). The first approach I tried was based on finding the circles and then looking for a grid pattern in their centroids.
This is the open-cv function I'm using:
circles = cv2.HoughCircles(bw_im,
cv2.cv.CV_HOUGH_GRADIENT,
dp=DP,
minDist=MIN_DIST,
minRadius=MIN_RADIUS,
maxRadius=MAX_RADIUS)
I add non-maximum suppression, but the results are not great.
Is there a better way than dealing with Hough circles directly, perhaps there is some sort of filled circularity morphological operation that I don't know of.
Here's an example input image:
You can assume that the input image has been cropped and has similar margins as above (I have another piece of code that takes care of this).
If Hough isn't a requirement, Id suggest implementing a ray-casting algorithm as described here: https://en.wikipedia.org/wiki/Point_in_polygon
The general steps are:
Create a mask for the red circles
Run ray-casting on x columns spaced y apart to determine # and position of reds
Repeat steps 1 & 2 for yellow
Since you're working in RGB, the color contrast should be enough to give you good results.
Assuming your grid will maintain its position the easiest way would be to setup a fixed region of interest for every slot and measure their hue values every time you change something.

Categories

Resources