Decode a 2D circle colour barcode - c++

I am new to opencv, coding in c++. I have a task given to me to decode a 2D circle barcode using an encoded array. I am up to the point where I am able to centralize the figure and get the line using Hough transforms.
Need help with how to read the colour in the images, note that each of the two adjacent blocks correspond to a letter.
Any pointers will be highly appreciated. Thanks.

First, you need to load the image. I suspect this isn't a problem because you are already using Hough transforms on it, but:
Mat img = imread(filename)
Once the image is loaded, you can grab any of the pixels using:
Scalar intensity = img.at<uchar>(y, x);
However, what you need to do is threshold the image. As I mentioned in the comments, the image colors are either 0 or 255 for each RGB channel. This is on purpose for encoding the data in case there are image artifacts. If the channel is above a certain color value, then you will consider that it's 'on' and if below, it's 'off'.
Threshold the image using adaptiveThreshold. I would threshold down to binary 1 or 0. This will produce RGB triplets that are one of eight (2^3) possible combinations, from (0,0,0) to (1,1,1).
Then you need to walk the pixels. This is where it gets interesting.
You say each adjacent 2 pixels form a single letter. That's 2^6 or 64 different letters. The next question is: are the letters arranged in scan lines, left-to-right, top to bottom? If yes, then it will be important to orientate the image using the crosshair in the center.
If the image is encoded radially (using polar coordinates) then things get a little trickier. You need to use cvLinearPolar to remap the image.
Otherwise you need to walk the whole image, stepping the size of the RGB blocks and discard any pixels whose distance from the center is greater than the radius of the circle. After reading all of the pixels into an array, group them by pairs.
At some point, I would say that using OpenCV to do this is heading towards machine learning. There has to be some point where you can cut in and use Neural Networks to decode the image for you. Once you have the circle (cutoff radius) and the image centered, you can convert to polar coordinates and discard everything outside the circle by cutting off everything greater than the radius of the circle. Remember, polar coordinates are (r,theta), so you should be able to cutoff the right part of the polar image.
Then you could train a Neural Network to take the polar image as input and spit out the paragraph.
You would have to provide lots of training data, and the trained model would still be reliant on your ability to pre-process the image. This will include any affine transforms in case the image is tilted or rotated. At that point you would say to yourself that you've done all the heavy lifting and the last little bit really isn't that hard.
However, once you get a process working for a clean image, you can start adding to steps to introduce ML to work on dirty images. HoughCircles can be used to detect the part of an image to run detection on. Next, you need to decide if the image inside the circle is a barcode or not.
A good barcode system will have parity bits or some other form of error correction, but you can use machine learning to cleanup output.
My 2 cents anyways.

Related

Finding regions of higher numbers in a matrix

I am working on a project to detect certain objects in an aerial image, and as part of this I am trying to utilize elevation data for the image. I am working with Digital Elevation Models (DEMs), basically a matrix of elevation values. When I am trying to detect trees, for example, I want to search for tree-shaped regions that are higher than their surrounding terrain. Here is an example of a tree in a DEM heatmap:
https://i.stack.imgur.com/pIvlv.png
I want to be able to find small regions like that that are higher than their surroundings.
I am using OpenCV and GDAL for my actual image processing. Do either of those already contain techniques for what I'm trying to accomplish? If not, can you point me in the right direction? Some ideas I've had are going through each pixel and calculating the rate of change in relation to it's surrounding pixels, which would hopefully mean that pixels with high rates change/steep slopes would signify an edge of a raised area.
Note that the elevations will change from image to image, and this needs to work with any elevation. So the ground might be around 10 meters in one image but 20 meters in another.
Supposing you can put the DEM information into a 2D Mat where each "pixel" has the elevation value, you can find local maximums by applying dilate and then substract the result from the original image.
There's a related post with code examples in: http://answers.opencv.org/question/28035/find-local-maximum-in-1d-2d-mat/

Detect Plants in a grass Image

I'm new in the Computer Vision.
I would like to detect some kind of plants in a grass images.
Original Image
Canny Edge Detection Algorithmus
Hough Line Transform (After Edge Detection)
I have already tried:
to remove the grass in the background with comparing th average of white pixels in a a region.
line detection with the hough line transform algorithm (the grass adds wrong lines)
What's in your opinion the best approach to detect this plant?
Dummy solution came in my mind. Since the grass is more detailed that the plant itself:
Apply Canny or any other edge detector.
Pass through the image using a window (let us say 10*10). For each window:
Compute the Density (number of white pixel if using Canny)
store it in array
Threshold the values in the array using Otsu algorithm. The less values represent the windows that are part of the plant.
Remap all needed window to the original picutre.
if a window is computed as not part of the object but in the same time it is surrouned by windows of the object, it is part of it.
Just for fun, and very similar to Humam's answer, just done using standard deviation instead of density, and making the image transparent where it doesn't think there are leaves. I used ImageMagick straight at the command line:
convert weed.jpg \( +clone -canny 0x1+10%+30% -statistic standarddeviation 10x10 -blur 0x8 -normalize -negate \) -compose copyopacity -composite result.png
I implemented Humam's approach.
But added some Steps after the Otsu algorithm:
Fulfill every black connected component
extract the mask with a matrix subtraction
Store the mask in a vector
sort it by area size (= sum(mask))
pick the biggest mask (=plant)
on the plant mask: do Step 1 -3 again
remove all small masks from the plant mask
I have some old and bad images from the plant, i'm going to test the algorithm the next days on these images.
unfortunately it's winter in my country and the grass is covered with snow. so i have to wait a couple of weeks to make some proper image from this plant.
Result of extraction.
The next step is to detect if the extracted image is the desired plant.

OpenCV C++ extract features from binary image

I have written an algorithm to process a camera capture and extract a binary image of two features I'm interested in. I'm trying to find the best (fastest) way of detecting when the two features intersect and where the lowest (y coordinate is greatest) point is (this will be the intersection).
I do not want to use a findContours() based method as this is too slow and, in my opinion, unnecessary. I also think blob detection libraries are too bloated for this.
I have two sample images (sorry for low quality):
(not touching: http://i.imgur.com/7bQ9qMo.jpg)
(touching: http://i.imgur.com/tuSmKw7.jpg)
Due to the way these images are created, there is often noise in the top right corner which looks like pixelated lines but methods such as dilation and erosion lose resolution around the features I'm trying to find.
My initial thought would be to use direct pixel access to form a width filter and a height filter. The lowest point in the image is therefore the intersection.
I have no idea how to detect when they touch... logically I can see that a triangle is formed when they intersect and otherwise there is no enclosed black area. Can I fill the image starting from the corner with say, red, and then calculate how much of the image is still black?
Does anyone have any suggestions?
Thanks
Your suggestion is a way more slow than finding contours. For binary images, finding contour is very easy and quick because you just need to find a black pixel followed by a white pixel or vice versa.
Anyway, if you don't want to use it, you can use the vertical projection or vertical profile you will see it the objects intersect or not.
For example, in the following image check the the letter "n" which is little similar to non-intersecting object, and the letter "o" which is similar to intersecting objects :
By analyzing the histograms you can recognize which one is intersecting or not.

Finding individual center points of circles in an image

I am using open CV and C++. I have a completely dark image which has 3 colored points on it. I need their center coordinates. If I have only one colored point in the dark image, it will automatically display its center coordinate. However,if I take as input the dark image with the 3 colored points,my program will make an average if those 3 coordinates and return the center of the 3 colored points together,which is my exact problem. I need their individual center coordinates.
Can anyone suggest a method to do that please. Thanks
Here is the code http://pastebin.com/RM7chqBE
Found a solution!
load original image to grayscale
convert original image to gray
set range of intensity value depending on color that needs to be detected
vector of contours and hierarchy
findContours
vector of moments and point
iterate through each contour to find coordinates
One of the ways to do this easily is to use the findContours and drawContours function.
In the documentation you have a bit of code that explains how to retrieve the connected components of an image. Which is what you are actually trying to do.
For example you could draw every connected component you will find (that means every dot) on it's own image and use the code you already have on every image.
This may not be the most efficient way to do this however but it's really simple.
Here is how I would do it
http://pastebin.com/y1Ae3e2V
I'm not sure this works however as I don't have time to test it but you can try it.

Find the best Region of Interest after edge detection in OpenCV

I would like to apply OCR to some pictures of 7 segment displays on a wall. My strategy is the following:
Covert Img to Grayscale
Blur img to reduce false edges
Threshold the img to a binary img
Apply Canny Edge detection
Set Region of Interest (ROI) base on a pattern given by the silhouette of the number
Scale ROI and Template match the region
How to set a ROI so that my program doesn't have to look for the template through the whole image? I would like to set my ROI base on the number of edges found or something more useful if someone can help me.
I was looking into Cascade Classification and Haar but I don't know how to apply it to my problem.
Here is an image after being pre-processed and edge detected:
original Image
If this is representative of the number of edges you'll have to deal with you could try a nice naive strategy like sliding a ROI-finder window across the binary image which just sums the pixel values, and doesn't fire unless that value is above a threshold. That should optimise out all the blank surfaces.
Edit:
Ok some less naive approaches. If you have some a-priori knowledge, like you know the photo is well aligned (and not badly rotated or skewed), you could do some passes with a low-high-low-high grate tuned to capture the edges either side of a segment, using different scales in both x and y dimensions. A good hit in both directions will give clues not only about ROI but what scale of template to begin with (too large and too small grates won't hit both edges at once).
You could do blob detection, and then apply your templates to blobs in turn (falling back on merging blobs if the template matching score is below a threshold, in case your number segment is accidentally partitioned). The size of the blob might again give you some hint as to the scale of template to apply.
First of all, given that the original image has a LED display and so the illuminated region is has a higher intensity than the trest, I'd perform say a Yuv colour transformation on the original image and then work with the intensity plane (Y).
Next, if you know that the image is well aligned (i.e. not rotated) I would suggest applying separate horizontal and vertical edge detectors rather than a generic edge detector (you are not interested in diagonal lines). E.g.
sobelx = cv2.Sobel( img, cv2.CV_64F, 1, 0, ksize=5 )
sobely = cv2.Sobel( img, cv2.CV_64F, 0, 1, ksize=5 )
Otherwise you might use contour detection to find the bounds of the digits (though you may need to perform a dilate to close the gaps between LED segments.
Next I would construct horizontal and vertical histograms of the output from these edge or contour detections. These would help you to identify 'busy' regions of the image which contain many edges.
Finally, I'd threshold the Y plane and explore each of the ROIs with my template.