I'm working on training OpenCV to detect an object using opencv_traincascade.
I see from the OpenCV documentation that there is an option to specify -bgcolorand -bgthresh for the positive images. From what I understand, this would set those pixels to clear and OpenCV would ignore them.
My questions:
Is this correct?
Would it be useful to shoot my objects against a green screen and specify the green as the background color?
Would anything be lost by doing that instead of shooting against a variety of backgrounds?
Yes
Yes -> This makes selecting the background color much, much easier.
The data of the backgrounds will be lost, but in most cases this is what you want. Otherwise, the trained data might recnogise the background more than the object.
Related
I always wanted to have a device that, from a live camera feed, could detect an object, create a 3D model of it, and then identify it. It would work a lot like the Scanner tool from Subnautica. Imagine my surprise when I found OpenCV, a free-to-use computer vision tool for Python!
My first step is to get the computer to recognize that there is an object at the center of the camera feed. To do this, I found a Canny() function that could detect edges and display them as white lines in a black image, which should make a complete outline of the object in the center. I also used the floodFill() function to fill in the black zone between the white lines with gray, which would show that the computer recognizes that there is an object there. My attempt is in the following image.
The red dot is the center of the live video.
The issue is that the edge lines can have holes in them due to a blur between two colors, which can range from individual pixels to entire missing lines. As a result, the gray gets out and doesn't highlight me as the only object, and instead highlights the entire wall as well. Is there a way to fill those missing pixels in or is there a better way of doing this?
Welcome to SO and the exiting world of machine vision !
What you are describing is a very classical problem in the field, and not a trivial one at all. It depends heavily on the shape and appearance of what you define as the object of interest and the overall structure, homogeneity and color of the background. Remember, the computer has no concept of what an "object" is, the only thing it 'knows' is a matrix of numbers.
In your example, you might start out with selecting the background area by color (or hue, look up HSV). Everything else is your object. This is what classical greenscreening techniques do, and it only works with (a) a homogenous background, which does not share a color with your object and (b) a single or multiple not overlapping objects.
The problem with your edge based approach is that you won't get a closed edge safely, and deciding where the inside and outside of the object is might get tricky.
Advanced ways to do this would get you into Neural Network territory, but maybe try to get the basics down first.
Here are two links to tutorials on converting color spaces and extracting contours:
https://docs.opencv.org/4.x/df/d9d/tutorial_py_colorspaces.html
https://docs.opencv.org/3.4/d4/d73/tutorial_py_contours_begin.html
If you got that figured out, look into stereo vision or 3D imaging in general, and that subnautica scanner might just become reality some day ;)
Good luck !
I am trying to create a line tracking program with a drone with a forward facing camera. I understood this could be a bit difficult since the camera was not facing downward and would pick up on the environment. I need it to face forward for a face recognition algorithm. So I chose to make the line pink. I found on this site some parameters for color filtering. I thought they would be over compensating with the color range, but the tape doesn't show up in a full sheet, but rather in a ton of boxes inside the tape.
def pinkThreshold(image):
copy = image.copy()
copy = cv2.cvtColor(copy,cv2.COLOR_RGB2HSV)
lower_pink = np.array([125,30,100])
upper_pink = np.array([225,255,255])
pinkImage = cv2.inRange(copy, lower_pink, upper_pink)
edges = cv2.Canny(pinkImage,240,255)
return edges
The image I get is this:
I think it might have to do with the camera returning red squares, but i'm not completely sure what I should do about this and if this is even the issue. The red pattern areas seem to be like what I have seen, but i'm not completely sure. If that is true, what would be a good color filter with pink and red? Also, would this be solved by a large floodlight over the line to be tracked?
The camera is attached to a DJI Tello drone. I can't change the equipment.
I think it might have to do with the camera returning red squares, but i'm not completely sure what I should do about this and if this is even the issue.
Let's adjust contrast and use color substitution to see the actual problem:
As you can see, color noise is huge. If you try to do color-based segmentation or try to apply any other "color sensitive logic" by targeting any specific color you are going to see that noise being picked up:
You can always improve your lighting conditions and extend the range you defined, but there is another approach: you can use multiple colors to find the actual shape you need, you can use thresholding to boost some specific areas and so on:
Long story short:
improve lightning conditions
AND/OR do some specific preprocessing with wider color range to properly address noise and overall quality of the picture
I have an image of some whole wheat/triticale grains upon the powdered grains. I need to segment these grains. As, background color is same as grain color, I cannot use color segmentation.
My question is how can i suppress background retaining only grain?
Thanks in advance
There are two possibilites i can think of:
Semantic segmentation e.g. with UNET
Have you tried basic edge detectors
I'd like to be able to detect the presence of a black box using opencv in an image. The black box itself may have various types of text and can vary in size. The rest of the image won't be black. Here are a few examples of the type of black boxes I'm referring to:
Obviously, template matching is a no-go, and using feature extraction also seems to be completely wrong since the only real features of the box are the lines of text (which are irrelevant). To my inexperienced computer vision senses it would seem that corner detection would be perhaps be the best approach. However, this still seems somewhat crude and imprecise for something as generic as a rectangle. Can someone suggest a more rigorous method for detection?
I am using this sprite for some experiments. I cropped a section of the sheet with GIMP and made the blue background transparent, the result being this. However, when I run the codes using this sprite, I still end up with a sprite with a blue background. Same thing happens with other sprites (different sprite sheet, same source, same editing process).
Now, I know that I can set transparent colors using PyGame itself but I'm wondering if that's the only way I can do it? Can't I do it through the image itself? How come PyGame still reads a blue backgorund even after I have cleared it with GIMP?
P.S. SSCE would be pvz_shooter_test.py and/or image_test.py of the GitHub repo linked.
Try mySurface.convert_alpha() (check the pygame documentation about it).
Just some more additional details on how come PyGame still read a blue background even after I've cleared it with GIMP.
When the image file format supports it, pixels aren't just represented as RGB bits. There's additional information for every pixel, the alpha channel. What GIMP did is to set the alpha bits to 0% opacity. The RGB values remained (in this instance, blue). Since my PyGame code isn't set to read the additional alpha bits, it only read the RGB describing blue. The convert_alpha method told PyGame to read the alpha channel as well.