Laser light detection with OpenCV and C++ - c++

I want to track a laser light dot(which is on a wall) with a webcam and i am using openCV to do this task. can anybody suggest me a way to do it with C++.
Thank you !

You have three options depending on the stability of your background, and the things you want to do with the image.
You can make your image so dark that the only thing you can see is the laser-point. You can do this by closing the diaphragm and/or reducing the shutter time. Even with cheap webcams this can usually be done in the driver. Once you've done this the job of finding the laser point is very easy. You make the image as dark as possible because usually the point where the laser shines is way too bright for the camera to pick up. This means (as you have experienced) that you cant discern between the light laser dot and other light objects in the image. By making it darker you now can do this.
If you have other uses for your image (showing it to people) and your background is stable you can also use the average of the last few video images as a "background" and then find the spot where there is a large difference between that background and the newest image. This is usually where the laser is pointed (again, if your background is stable enough) .
Finally, if your background is not stable and you don't want to make your image very dark your final option is to look for all pixels that are both very bright, and brighter in the red channel than they are in green and blue (if you are using a red laser). This system will still be distracted by white spots, but not as much as just finding the bright pixels. If the center of your laser-pointer spot is indeed showing up as bright white regardless of laser color then this technique will allow you to find "rings" around this bright spot (the outer part of the dot where the laser is not as bright as it is in the center so that it shows up with the actual color of the laser in the image). You can then use simple morphological operations, (probably closing is enough) to fill these circles.

Let say you use a laser of one of these colors: red, green, blue.
If the laser dot appears very bright (at least in one channel, e.g. red) then simply thresholding the image/channel at, say greyvalue of 200, will leave you with a few candidates for the laser light. If the other channels are dark(er) in this area, then you know it is a bright light of the right color. A little filtering by size, and you have a good chance of finding the spot.

If you stick a IR filter on your webcam, your projection will not be picked up, making the detection of the laser point much easier (using simple background subtraction e.t.c) That's assuming the laser pointer emits IR light...

As suggested in other answers, searching for the color might be a good idea.
You should consider to look for a specific color range. Best way to do this is to convert the picture to HSL or HSV color space.
cv::cvtColor(src, hsv, COLOR_BGR2HSV);
More information on Wikipedia.
Then you have three channels:
hue (=color), saturation and lightness( or value).
With cv::inRange(hsv, cv::Scalar(159, 135, 165), cv::Scalar(179, 255, 200), inRange); you can now generate a Black and white image, which shows what pixels are in the color range.
The scalars are the low and high values for each channel.
In this example you will get pixels with a color between 159 and 179 (hue), saturation between 135 and 255 and value between 165 and 200.
Maybe this can improve your tracking.

How about this code
https://www.youtube.com/watch?v=MKUWnz_obqQ
https://github.com/niitsuma/detect_laser_pointer
In this code, observed HSV color is compared to registered color using Hotelling's t square test

try Template Maching.
first you "point the pointer" to an specific place so the temple can be done. Then you just look for it.
Or, as jilles de wit said, you can take the difference of the last 2 frames, probably the difference will show you the pointer.
Convert the last 2 frames do gray scale, then apply the SUB function.

Related

Getting Hue value from the peaks in histogram opencv

I am trying to use color information of detection of rectangles. Some of my rectangles are overlapping and with multicolor. I found a solution to detect these rectangles using Hue values. I am checking inRange with Hue values of colors
Orange 0-22
Yellow 22- 38
Green 38-75
Blue 75-130
Violet 130-160
Red 160-179
, but I do not know what exact color is going to be. For example, in one image rectangles can be orange, red, blue and in another image, it can be other colors.
I tried to look histogram, but I would have a background which is not only white or black. So, the histogram is confusing.
If you give me some ideas about how to handle this problem, I will appreciate it.
You can try a brute force approach, where you try all the color ranges, then use findcontours (example) to see if you can find a contour that is possibly a rectangle. If the background is very noisy you can use a minimum size for the contour
(contourArea). You could also check the solidity by dividing the contour area by the area of the minAreaRect, the result for a rectangle (that has good detection) should approach 1.
Whether this could possibly work depends on several factors, and overlapping rectangles will quickly break it.
So if I understand correctly, you have a variety of images, each of which contain multiple rectangles which can be a variety of different colors, and the background of the image is non uniform, and you're trying to segment out the rectangles using a histogram?
Using histograms for image segmentation works best with grey scale images with a uniform background, so that upon seeing the peeks in your histogram you know the primary intensities of the objects you are trying to segment out. This method is not going to translate well to your application because the shapes you are attempting to segment are non uniform in shade, without seeing example images I would probably say this isn't going to work, however you might be able to get away with it if the shade variation of the rectangles is relatively similar... basically if you have rectangles that are 15-30 you might be alright, but if they vary from 20-100 you're going to be out of luck, same goes with variation of the background.
If the background and the rectangles have very clearly defined borders, and the background colors transition VERY smoothly, you may be able to get away with some sort of region growing on the background in order to get a list of all the background pixels and then just set those to black or something in order to allow better analysis of the rectangles in the foreground, but I can only speculate so much with the information you've given in your post

Infrared images segmentation using OpenCV

Let's say I have a series of infrared pictures and the task is to isolate human body from other objects in the picture. The problem is a noise from other relatively hot objects like lamps and their 'hot' shades.
Simple thresholding methods like binary and/or Otsu didn't give good results on difficult (noisy) pictures, so I've decided to do it manually.
Here are some samples
The results are not terrible, but I think they can be improved. Here I simple select pixels by hue value of HSV. More or less, hot pixels are located in this area: hue < 50, hue > 300. My main concern here is these pink pixels which sometimes are noise from lamps but sometimes are parts of human body, so I can't simply discard them without causing significant damage to the results: e.g. on the left picture this will 'destroy' half of the left hand and so on.
As the last resort I could use some strong filtering and erosion but I still believe there's a way somehow to told to OpenCV: hey, I don't need these pink areas unless they are part of a large hot cluster.
Any ideas, keywords, techniques, good articles? Thank in advance
FIR data is presumably monotonically proportional (if not linear) to temperature, and this should yield a grayscale image.
Your examples are colorized with a color map - the color only conveys a single channel of actual information. It would be best if you could work directly on the grayscale image (maybe remap the images to grayscale).
Then, see if you can linearize the images to an actual temperature scale such that the pixel value represents the temperature. Once you do this you can should be able to clamp your image to the temperature range that you expect a person to appear in. Check the datasheets of your camera/imager for the conversion formula.

C++/OpenCV find objects on an image

I have to find a couple of objects on an image. For example find all black pawns on a chessboard:
How can I achieve that,using OpenCV ?
I think about cv::matchTemplate, however I'm not sure how would it proceed with different pawn backgrounds. I'm also not sure if I can easily get all matchings in that way.
Start with corner detection (well known shi tomasi method, or smt like line detection and intersection, since it should work better for your case) and collection of 64 subsamples of image -the squares. If the board is ideal - pure birds eye view -and you know the size (8x8 here), then just crop it into WxH pieces. You should save these samples with their coordinates (b6, h1 etc).
For every square, a low pass filter smt like gaussian, then otsu threshold and contour detection should give you at most one big contour. If there is none, that square is empty.
You can try to get the contours from the initial state of the board, and name them. This is your training data. Since pieces are not gonna differ much; 1 sample is enough :) Save a "white pawn"s (any square from 2nd row initially) area, hu moments and color (mean rgb value is OK). Then save a "black pawn". Then "white queen" and "black queen" (d4 d8). Do that area, moment, color table for all pieces.
Later, for any state of the board, you can try to match hu moments, color and area of your contour -output of those squares, using your identification table. Of course some statistical method like knn could help you there. You can also utilize matchShapes method.
At last you identify your contour smt like black knight, red checker piece, etc.

Dynamic background separation and reliable circle detection with OpenCV

I am attempting to detect coloured tennis balls on a similar coloured background. I am using OpenCV and C++
This is the test image I am working with:
http://i.stack.imgur.com/yXmO4.jpg
I have tried using multiple edge detectors; sobel, laplace and canny. All three detect the white line, but when the threshold is at a value where it can detect the edge of the tennis ball, there is too much noise in the output.
I have also tried the Hough Circle transform but as it is based on canny, it isn't effective.
I cannot use background subtraction because the background can move. I also cannot modify the threshold values as lighting conditions may create gradients within the tennis ball.
I feel my only option is too template match or detect the white line, however I would like to avoid this if possible.
Do you have any suggestions ?
I had to tilt my screen to spot the tennisball myself. It's a hard image.
That said, the default OpenCV implementation of the Hough transform uses the Canny edge detector, but it's not the only possible implementation. For these harder cases, you might need to reimplement it yourself.
You can certainly run the Hough algorithm repeatedly with different settings for the edge detection, to generate multiple candidates. Besides comparing candidates directly, you can also check that each candidate has a dominant texture (after local shading corrections) and possibly a stripe. But that might be very tricky if those tennisballs are actually captured in flight, i.e. moving.
What are you doing to the color image BEFORE the edge detection? Simply converting it to gray?
In my experience colorful balls pop out best when you use the HSV color space. Then you would have to decide which channel gives the best results.
Perhaps transform the image to a different feature space might be better then relying on color. Maybe try LBP which responds to texture. Then do PCA on the result to reduce the feature space to 1 single channel image and try Hough Transform on that.

Getting and comparing object's color from image

My aim is to determine the color of object. And make a classification, for example some blue, little bit dark blue or light blue can be classified to one type - Blue. I have some template objects images. There are many of them. What I want is to group this images manually. For example some objects have blue colored text, but some areas of yellow etc. By some algorithm at first I group them manually, and then each group should be analyzed by computer to make some feature extraction. And then while getting from camera as video or image of the random selected object, I want to identify it's group correctly. How can I do it? Which features should be extracted and how can they be compared? I was thinking of histogram of a Hue plane in HSV. But don't know what features to get from that histogram and then to compare it with another(from template images)
EDIT 1: Example of images that should be classified, later will post more if neccessary.
image example
It is always good to use the LAB color space in order to mimic human perception.
http://en.wikipedia.org/wiki/Lab_color_space
That is because the Euclidean metric in this color space represents the perceptual distance between colors, that is, how close they are.
You should cluster by A,B and ignore L value which is the brightness.
HSV can be tricky to use in varying light situations. This is especially true outside, where shadows are a lot bluer than sunlight areas.
Ideally, you can use the hue and saturation components and ignore the value component. This would make the distance between a light blue and a dark blue very small:
dist = sqrt((h1 - h2)^2 + (s1 - s2)^2
The gotcha is that hue is actually a continuous scale (like an angle). The difference between 255 and 0 should only be 1.