detect card symbol using opencv python - python

I'm trying to detect the difference between a spade, club, diamond and hart. the number on the card is irrelevant, just the suit matters.
i've tried color detection by looking at just the red or black colors, but that still leaves me with two results per color. how could i make sure i can detect each symbol individually?
for instance: i have a picture of a red hart, a red diamond, a black spade and a black club. i want to draw the contours of each symbol in a different color.
I'm using my webcam as a camera.

If the suit of your cards is always identical (only one single kind of card) you could just store images of spade, club, diamond and hart and then check the cross-correlation of the given image to your references and pick the highest value (see this question). If you have a fairly large sample set of different kinds of cards that have slight differences between the suit-representations you can pretty much follow this tutorial almost exactly to do a four-way classification of your training set and use a svm, clustering or other approaches, which are available in open-cv.
hope this helps and all the best

I don't see any code, so can't really tweak what you have, but more generally you ought to be able to train it just the same except for the symbol instead of color:
Here is a sample code for doing a specific card. You can either train them to be card specific, thus capturing all of the symbols by specific card, or back it up and more generally train for the symbol (heart / diamond). You should also look at template matching on opencv.
There are a couple guides and code already completed for this on github.
Here is a tutorial worth reading

As the card symbol is at fixed positions, you may try below (e.g. in OpenCV 3.2 Python):
Crop the symbol at top left corner, image = image[h1:h2,w1:w2]
Threshold the symbol colors to black, the rest to white, thresh = mask = cv2.inRange(image,(0,0,0),(100,100,100))
Perform a find contour detection, _, contours, hierarchy = cv2.findContours()
Get the area size of the contour. area = cv2.contourArea(contour)
Compare the area to determine which one of the 4 symbols it belongs to.
In which you have to build the area thresholds of each symbol for step 4 to compare. All the cv2 functions above are just for reference.
Hope this help.

Unless you have major perspective distortion (when it may work anyway), template matching is very effective. You can run this in red and black channels separately (obviously don't look for red spades etc.).
Take a look at e.g. (not mine)
http://www.pyimagesearch.com/2015/01/26/multi-scale-template-matching-using-python-opencv
For playing cards, see also https://github.com/arnabdotorg/Playing-Card-Recognition

Related

Why isn't my pink color mask returning a continuous shape

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

Detect overlapping players from a blob

is there a way to detect the number of overlapping players in a blob?
I do contour detection and each detected contour is a player but how to know if there are players that a very close to each other that they are considered one.
for example to know that
this blob
has two players like in
this image.
If you didn't want to use machine learning you could try using the area of the contours by assigning a threshold. Generally speaking 1 person should only take up so much space, beyond that point you could assume that there MUST be someone else there by the area that is taken up.
Also depending on the teams clothing colors it would be pretty easy to extract contours by color. Red+blue for 1 team and white for the other in this example. Hope this helps!

Detect region from edges

I've got a micrograph showing a number of grains that have a rather clear boundary. I've used OpenCV-Python to detect these boundaries (with a Canny filter), and I think it was rather successful in its attempt, see figure. I would like to identify and mark the individual regions bounded by the detected edges, and then get the area (number of pixels) contained those regions. My apologies if the question was asked (and answered) before, but I could not find any satisfying answers yet.
Thanks in advance
Original image
Original image overlain by the detected edges
If the grain makes no difference in the color (maybe on the raw data rather than a compressed format), you may wanna use the Becke line to distinguish inside and outside. The borders of your grain appear dark on the inside and white on the outside. But this depends also on the focus of the microscope. See here.
In the case that your grains do not enclose totally a background spot you can use a point in polygon approach.

Robust Hand Detection via Computer Vision

I am currently working on a system for robust hand detection.
The first step is to take a photo of the hand (in HSV color space) with the hand placed in a small rectangle to determine the skin color. I then apply a thresholding filter to set all non-skin pixels to black and all skin pixels white.
So far it works quite well, but I wanted to ask if there is a better way to solve this? For example, I found a few papers mentioning concrete color spaces for caucasian people, but none with a comparison for asian/african/caucasian color-tones.
By the way, I'm working with OpenCV via Python bindings.
Have you taken a look at the camshift paper by Gary Bradski? You can download it from here
I used the the skin detection algorithm a year ago for detecting skin regions for hand tracking and it is robust. It depends on how you use it.
The first problem with using color for tracking is that it is not robust to lighting variations or like you mentioned, when people have different skin tones. However this can be solved easily as mentioned in the paper by:
Convert image to HSV color space.
Throw away the V channel and consider the H and S channel and hence
discount for lighting variations.
Threshold pixels with low saturation due to their instability.
Bin the selected skin region into a 2D histogram. (OpenCV"s calcHist
function) This histogram now acts as a model for skin.
Compute the "backprojection" (i.e. use the histogram to compute the "probability"
that each pixel in your image has the color of skin tone) using calcBackProject. Skin
regions will have high values.
You can then either use meanShift to look for the mode of the 2D
"probability" map generated by backproject or to detect blobs of
high "probability".
Throwing away the V channel in HSV and only considering H and S channels is really enough (surprisingly) to detect different skin tones and under different lighting variations. A plus side is that its computation is fast.
These steps and the corresponding code can be found in the original OpenCV book.
As a side note, I've also used Gaussian Mixture Models (GMM) before. If you are only considering color then I would say using histograms or GMM makes not much difference. In fact the histogram would perform better (if your GMM is not constructed to account for lighting variations etc.). GMM is good if your sample vectors are more sophisticated (i.e. you consider other features) but speed-wise histogram is much faster because computing the probability map using histogram is essentially a table lookup whereas GMM requires performing a matrix computation (for vector with dimension > 1 in the formula for multi-dimension gaussian distribution) which can be time consuming for real time applications.
So in conclusion, if you are only trying to detect skin regions using color, then go with the histogram method. You can adapt it to consider local gradient as well (i.e. histogram of gradients but possibly not going to the full extent of Dalal and Trigg's human detection algo.) so that it can differentiate between skin and regions with similar color (e.g. cardboard or wooden furniture) using the local texture information. But that would require more effort.
For sample source code on how to use histogram for skin detection, you can take a look at OpenCV"s page here. But do note that it is mentioned on that webpage that they only use the hue channel and that using both hue and saturation would give better result.
For a more sophisticated approach, you can take a look at the work on "Detecting naked people" by Margaret Fleck and David Forsyth. This was one of the earlier work on detecting skin regions that considers both color and texture. The details can be found here.
A great resource for source code related to computer vision and image processing, which happens to include code for visual tracking can be found here. And not, its not OpenCV.
Hope this helps.
Here is a paper on adaptive gaussian mixture model skin detection that you might find interesting.
Also, I remember reading a paper (unfortunately I can't seem to track it down) that used a very clever technique, but it required that you have the face in the field of view. The basic idea was detect the person's face, and use the skin patch detected from the face to identify the skin color automatically. Then, use a gaussian mixture model to isolate the skin pixels robustly.
Finally, Google Scholar may be a big help in searching for state of the art in skin detection. It's heavily researched in adademia right now as well as used in industry (e.g., Google Images and Facebook upload picture policies).
I have worked on something similar 2 years ago. You can try with Particle Filter (Condensation), using skin color pixels as input for initialization. It is quite robust and fast.
The way I applied it for my project is at this link. You have both a presentation (slides) and the survey.
If you initialize the color of the hand with the real color extracted from the hand you are going to track you shouldn't have any problems with black people.
For particle filter I think you can find some code implementation samples. Good luck.
It will be hard for you to find skin tone based on color only.
First of all, it depends strongly on the automatic white balance algorithm.
For example, in this image, any person can see that the color is skin tone. But for the computer it will be blue.
Second, correct color calibration in digital cameras is a hard thing, and it will be rarely accurate enough for your purposes.
You can see www.DPReview.com, to understand what I mean.
In conclusion, I truly believe that the color by itself can be an input, but it is not enough.
Well my experience with the skin modeling are bad, because:
1) lightning can vary - skin segmentation is not robust
2) it will mark your face also (as other skin-like objects)
I would use machine learning techniques like Haar training, which, in my opinion, if far more better approach than modeling and fixing some constraints (like skin detection + thresholding...)
As more robust then pixel colour you can use hand geometry model. First project model for particular gesture and the cross-correlate it with source image. Here is demo of this tchnique.

Determine height of Coffee in the pot using Python imaging

We have a web-cam in our office kitchenette focused at our coffee maker. The coffee pot is clearly visible. Both the location of the coffee pot and the camera are static. Is it possible to calculate the height of coffee in the pot using image recognition? I've seen image recognition used for quite complex stuff like face-recognition. As compared to those projects, this seems to be a trivial task of measuring the height.
(That's my best guess and I have no idea of the underlying complexities.)
How would I go about this? Would this be considered a very complex job to partake? FYI, I've never done any kind of imaging-related work.
Since the coffee pot position is stationary, get a sample frame and locate a single column of pixels where the minimum and maximum coffee quantities can easily be seen, in a spot where there are no reflections. Check the green vertical line segment in the following picture:
(source: nullnetwork.net)
The easiest way is to have two frames, one with the pot empty, one with the pot full (obviously under the same lighting conditions, which typically would be the case), convert to grayscale (colorsys.rgb_to_hsv each RGB pixel and keep only the v (3rd) component) and sum the luminosity of all pixels in the chosen line segment. Let's say the pot-empty case reaches a sum of 550 and the pot-full case a sum of 220 (coffee is dark). By comparing an input frame sum to these two sums, you can have a rough estimate of the percentage of coffee in the pot.
I wouldn't bet my life on the accuracy of this method, though, and the fluctuations even from second to second might be wild :)
N.B: in my example, the green column of pixels should extend to the bottom of the pot; I just provided an example of what I meant.
Steps that I'd try:
Convert the image in grayscale.
Binarize the image, and leave only the coffee. You can discover a good threshold manually through experimentation.
Blob extraction. Blob's area (number of pixels) is one way to calculate the height, ie area / width.
First do thresholding, then segmentation. Then you can more easily detect edges.
You're looking for edge detection. But you only need to do it between the brown/black of the coffee and the color of the background behind the pot.
make pictures of the pot with different levels of coffe in it.
downsample the image to maybe 4*10 pixels.
make the same in a loop for each new live picture.
calculate the difference of each pixels value compared to the reference images.
take the reference image with the least difference sum and you get the state of your coffe machine.
you might experiment if a grayscale version or only red or green might give better results.
if it gives problems with different light settings this aproach is useless. just buy a spotlight for the coffe machine, or lighten up, or darken each picture till the sum of all pixels reaches a reference value.

Categories