Finding simple template in image of unknown scale - c#

I have a floor layout (fairly simple, white background, black content) and a template of a chair on the floor. I know all orientations I need to look for (simple up, down, left, right) but I do not know the scale of the floor template coming in.
I have it working with AForge where, when copying a chair from the layout so I know the exact scale, I can find all chairs on the floor. That is giving me exactly what I want (I just need the center x,y of the chair). Going forward I would like to automate this. I won't know the exact scale of the floor plan being uploaded
I played with the Emgu.CV examples to try and find it (SURFFeature example project) but using just the chair as the template did not work. It doesn't seem to find any observedDescriptors (it is null), I assume because the chair on its own isn't too complex. I tried a more complex template (chair+desk, though it wouldn't work normally because the chair relative to desk isn't consistent). The results didn't seem useful, it pointed to a few random places on the floor plan but didn't seem quite right.
Any ideas on ways to determine the scale?

By using the wrong scale, readings are not accurate. This may cause a package weight to be misprinted on a cereal box that is made floor scale instead of a balance scale. This is because the percision on these scales is different to accommodate a business's diverse needs. And, by using different calabrations, this can cause a difference in the weight between an identical product when measured on a floor scale and than a counting scale.

Alright, I was able to get this working. What I ended up doing is drawing a square inside a circle and placing the object I want inside the square
Then I use: Blob[] blobs = blobCounter.GetObjectsInformation( ); to get all blobs on the page.
Loop through the blobs and look for all circles and squares, add them to a list of each
if (shapeChecker.IsCircle(edgePoints, out center, out radius))
{
circs.Add(b);
}
else if (corners.Count == 3)
tris.Add(b);
else if (corners.Count == 4)
boxes.Add(b);
Loop through each circle, and for each circle all squares, and look for two with approximately the same center point.
To get the object inside I copy a crop of the image from inside the square (add a few to x,y, remove a few from width, height). This gives me the white space and object within the square
I then use an autocrop (from here, though modified because I didn't need to rotate/greyscale) to cut away the white space and am left with just the image I want!
sorry I don't have example images in this - I don't have enough rep to post them yet

Related

c# detect points of polygon in black/white image

I have to detect all the points of a white polygon on a black background in c#. Here is an image of several examples. I wouldn't think it is too difficult, but I am unable to detect this properly with all the variations. My code is too much to post here, but basically I went through each side and look for when it changes from black and white. Should I use Open CV? I was hoping for a simple algorithm I could implement in C#. Any suggestions? Thank you.
In your case I would do this:
pre process image
so remove noise in color if present (like JPG distortion etc) and binarize image.
select circumference pixels
simply loop through all pixels and set each white pixel that has at least one black neighbor to distinct color that will represent your circumference ROI mask or add the pixel position to some list of points instead.
apply connected components analysis
so you need to find out the order of the points (how are connected together). The easiest way to do this is use flood filing of the ROI from first found pixel until all ROI is filled and remember the order of filled points (similar to A*). There should be 2 distinct paths at some point and both should join at last. So identify these 2 points and construct the circumference point order (by reversing one half and handling the shared part if present).
find vertexes
if you compute the angle change between all consequent pixels then on straight lines the angle change should be near zero and near vertexes much bigger. So threshold that and you got your vertexes. To make this robust you need to compute slope angle from a bit more distant pixels then the closest pixels. Also thresholding this angle change against sliding average often provides more stable results.
So find out how far the pixels should be to compute angle so you got not too big noise and vertexes has still big peaks and also find out the threshold value that is safe above any noise.
This can be done also by hough transform and or find contours functions that are present in many CV libs. Another option is also regress/fit the lines in the point list directly and compute intersections which can provide sub pixel precision.
For more info see related QAs:
Backtracking in A star
Finding holes in 2d point sets
growth fill

OpenCV/EMGU (C#) detection of objects

I'm trying to write some image detection code for a pick and place machine. I'm new to OpenCV and have been going through a lot of examples - but still ahve two outstanding questions. The first one I think I have a solution for but I'm lost on the second.
I'm trying to detect the offset and angle of the bottom of a part. Essentially, how far is the object from the cross (just an indicator of the center of the frame), and what the angle of rotation the part has about the part's center. I've used filters to show the pads of the components.
I'm pretty sure that I want to implement something like this http://felix.abecassis.me/2011/10/opencv-bounding-box-skew-angle/ - but I'm not sure how to translate the code into C# (http://www.emgu.com/wiki/index.php/Main_Page). Any pointers would be helpful.
One issue is if the part is smaller than the needle that's holding it and you can see both the part and the needle.
The square bit is the part I want to detect. The round part is part of the needle that is still exposed. I've got no clue how to approach this - I'm thinking something along the lines of detecting the straight lines and discarding the curved ones to generate a shape. Again, I'm interested in the offset from the center and the angle of rotation.
First you should detect every Object with findContours. Then you can use the minimum area rectangle function on every found contour. I assume you know the size and coordiantes of your cross so you can use the Center Coordinates of the MCvBox2D to get the Offset to it. Furthermore you can read the angle property of the box so it should fit your purpose.
For the second part i would try to fit a least square reactangle. The round part seems to be very small compared to the square one so maybe it will work.
Maybe the Detection of Quadrilaterlas in the AForge Library could help you too.
Edit:
To merge your the contours i would try something like this:
Rectangle merged = New Rectangle(New Point(img.Width, img.Height), New Size(0, 0)); //img is your binarized image
Contour<Point> Pad_contours= img.FindContours(CvEnum.CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_SIMPLE,CvEnum.RETR_TYPE.CV_RETR_LIST);
while(Pad_contours !=null)
{
if(Pad_contours.Area <Pad_Area_max &&Pad_contours>Pad_Area_min)//Filter Pads to avoid false positive Contours
{
//Merge Pad contours into a single rectangle
if(merged.Height >0)
merged.Bottom=Math.Max(merged.Bottom,Pad_Contours.BoundingRectangle.Bottom);
else
merged.Height = contours.BoundingRectangle.Height;
merged.Top=Math.Min(merged.Top,Pad_Contours.BoundingRectangle.Top);
merged.Left=math.Min(merged.Left,Pad_Contours.BoundingRectangle.Left);
if(merged.Width>0)
merged.Right=Max(merged.Right,pad_Contours.BoundingRectangle.Right);
else
merged.Width=Pad_Contours.BoundingRectangle.Width;
}
//get next Pad
If(Pad_contours.VNext==null)
Pad_contours=Pad_contours.HNext;
else
Pad_contours = Pad_contours.VNext;
}
The rectangle "merged" should enclose all your Pads now. The problem is you wont get an angle this way because the rectangle is always vertically 90°. To solve this I would iterate through the contours like shown above and store every point of every contour in an extra datacontainer. Then I would use the minimum area rectangle function mentioned above and apply it on all gathered points. This should give you a bounding rectangle with an angle property.

Virtual Hair on Detected face using Emgu CV - C#

My current project has required me to learn face detection/tracking and image processing, given my experience in c#, I chose Emgu CV as my choice library for face detection and tracking. From what I've learned so far, I can do face detection and tracking, and basic image processing.
My goal is to be able to place virtual hair on the detected face. What I want to achieve is similar to [this video]: http://www.youtube.com/watch?v=BdPmECfUFcI.
What I would like to know is the technique(s) to use in handling hair placement for different kind of hairstyles on the detected face. In what image format do I store the the hair?
After watching the video I noticed it considers the head as a flat rectangle and not as a rectangular prism (the 3D object), so it doesn't consider the use of perspective transformations and I will not consider it too. This is a limitation but serves as a decent first step in doing such placements. Note that it is not a simply matter of taking perspective into consideration, your face tracking algorithm also needs to be able to handle more complicated configurations (the eyes might not be fully visible, for example).
So, the first thing you want is a bounding rectangle aligned according to the angle the eyes make with the x axis, illustrated in the following right figure (the red segment indicates the connection between the eyes). The left figure shows a typical bounding box aligned to the axis, which doesn't serve for this problem.
The problem is also simplified after you consider the head is symmetric, so you know the top middle point in the above figure is the middle of the top of your head. Also, considering that a typical head will likely be larger at top than at bottom, then you have something like in the following figure where the width of the rectangle is close to the width of the forehead. You could also consider a bounding rectangle on only upper half of the head, for example.
Now all that is left is positioning some object in this rectangle. For that, you need to augment the description of this object to be positioned so it is not purely pixels. We can define "entrance width" (EW) and "entrance middle point" (EM). This EW establishes the width needed in the other rectangle (the head one) to position it. So, if EW is smaller than the needed value, you upscale this object, respectively for when EW is larger. Note that the full width of the head's rectangle is usually an overestimation to position this object, so you can experiment with percentages of the width. The EM value is useful to know how you will position this object over the head. In the following figure, EW is the horizontal blue dashed horizontal, and EM is the middle point on it. The vertical blue line indicates how much over the EM you want to move this object inside the top segment of head's rectangle.
The only other special thing this object needs is a value that is considered as background. So when painting this object it is easy to know whether to make a point fully transparent (the background value) or fully opaque (anything else). This was the sketch I had in mind of what needs to be basically done.

How to find a shape in a series of mouse clicks?

I was wondering how (if at all) it would be possible to determine a shape given a set of X,Y coordinates of mouse clicks?
We're dealing with a number of issues here, there may be clicks (coords) which are irrelevant to the shape. Here is an example: http://tinypic.com/view.php?pic=286tlkx&s=6 The green dots represent mouse clicks, and the search is for a square at least x in height/width, at most y in height/width and compromised of four points, the red lines indicate the shape found. I'd like to be able to find a number of basic shapes, such as squares, rectangles, triangles and ideally circles too.
I've heard that Least Squares is something that would help me, but it's not clear to me how this would help me if at all. I'm using C# and examples are more than welcome :)
You can create detectors for each shape you want to support. These detectors will tell, if a set of points form the shape.
So for example you would pass 4 points to the quad detector and it returns, if the 4 points are aligned in a quad or not. The quad detector could work like this:
for each point
find the closest neighbour point
compute the inner angle
compute the distance to the neighbours
if all inner angles are 90° +- some threshold -> ok
if all distances are equal +- some threshold (percentage) -> ok
otherwise it is no quad.
A naive way to use these detectors is to pass every subset of points to them. If you have enough time, then this is the easiest way. If you want to achieve some performance, you can select the points to pass a bit smarter.
E.g. if quads are always axis aligned, you can start at any point, go right until you hit another point (again with some thresold), go down, go left.
Those are just some thoughts that might help you further. I can imagine that there are algorithms in AI that can solve this problem in a more pragmatic way, maybe neural networks.

Rotating part of an image in 3D space

Here's the setup: This is for an ecommerce art site where some paintings are canvas transfers. The painting wraps around the sides and top and bottom of the canvas. We have high-res images of the entire painting, but what we want to display is a quasi-3D representation of the image in which you can see how the sides of the painting wrap around the canvas. Here's a rough sketch of what I'm talking about:
My question is, how can I rotate an image in 3D space? The approach I think I'd like to take, is to cut off a portion of the top and side of the image, and rotate then in 3D and then stich it back on to the top and side to give it the 3D look. How do I go about about doing that? It can be done using any .Net technology (GDI+, WPF etc.).
In WPF using the ViewPort3D class you can create a cuboid which is 8x5x1 units. Create the image as a texture and then apply the texture to the front face (8x5) and the side faces (5x1) and the top and bottom faces (8x1) using texture coordinates. The front face coordinates should be: (1/9, 1/6), (8/9, 1/6), (1/9, 5/6) and (8/9, 5/6) for the front face, and from the nearest edge to those coordinates for the sides, e.g. for the left side: (0, 1/6), (1/9, 1/6), (0, 5/6) and (1/9, 5/6) for the left side.
Edit:
If you then want to be able to perform rotations on the 3D canvas model you can follow the advice here:
How can I do 3D transformation in WPF?
It looks like you're not needing to do real 3D, but only needing to fake it.
Chop off four strips along the top, bottom, left and right of the image. Toss the bottom and right (going by your sketch in the question). Scale and shear the strips (I'm not expert enough at .net/wpf to know how, but it can do it). The top would be scaled vertically by a factor of 0.5 (a guess - choose to fit the desired final 3D-looking image) and sheared horizontally. The result is composited onto the output image as the top side of the canvas. The left strip would be scaled horizontally and sheared vertically.
If the end user is to view the 3D canvas from different angles interactively, this method is probably faster than rendering an honest 3D model, which would have to do texture mapping and rasterizing the model into a final image, which amounts to doing the same math. The fun part is figuring out how to adjust the scaling and shearing parameters.
This page might be educational: http://www.idomaths.com/linear_transformation.php
and this could be useful reference http://en.csharp-online.net/GDIplus_Graphics_Transformation%E2%80%94Image_Transformation
I dont have any experience in this kind of stuff. But when i saw this question, the first thing comes to my mind is the funny Unicornify for SO.
In this making of article by balpha, he explained how the 2d unicorn sphere is rotated in 3d space.
But the code is written in python. If you are interested, you can take a look into that. But am not exactly sure this would help you.
The brute force approach (which might be the easiest approach), is to map the u,v texture coordinates for each of the three faces, onto three billboards representing three sides of the canvas (a billboard is just two triangles that make a rectangle). Then, rotate the whole canvas (all three billboards) using matrix transforms. Tada!
Alternately, you can move the 3-space camera position with a transform, rather than the canvas. Six of one, half the other - as they say.

Categories

Resources