How to complete a square using 4 lines by emgucv c#? - c#

How to complete a square using 4 lines?
<- Please see the picture.
the square
trying to find a min' square
Hi, I work with EMGUcv and I am supposed to identify 4 lines from which to complete an exact square. Maybe someone has an idea? I tried to find the least square but it is not exact and it is difficult to work with the results of it.
Thanks.
Image<Bgr, Byte> Clean_Image = new Image<Bgr, Byte>(Original).CopyBlank();
Method.ERectangle ERRectangle = null;//<------my Rectangle object..
if (Pointlist.Count > 0)
{
ERRectangle = new Method.ERectangle(Emgu.CV.CvInvoke.MinAreaRect(Pointlist.ToArray()));
Size s = new Size((int)Method.LineSize(ERRectangle.MainRectangle.Points[0], ERRectangle.MainRectangle.Points[2]),(int)Method.LineSize(ERRectangle.MainRectangle.Points[1], ERRectangle.MainRectangle.Points[3]));
Method.ERectangle rRect = new Method.ERectangle(new RotatedRect(ERRectangle.Center, s, (float)ERRectangle.ContourAngle-(float)45));
//I tried to find a square and align with the lines.. A possible idea but not accurate
Emgu.CV.CvInvoke.Polylines(Clean_Image, rRect.MainRectangle.Points.ToArray(), true, new MCvScalar(255, 0, 0), 7);
}

Related

OpenCV How to find seam lines in an image?

After the InRange and GaussianBlur function, I get the following image:
I find the edges and I get:
I need to get from this image three lines, which are represented in the following image (lines that are not red are bulging nodes):
How can I do that?
You should use an Erosion operation with a clever structuring element.
I suggest to use one with the length of the longest horizontal line to remove.
I've made a little example:
Let's take this toErode.png
double longestHorLine = 201;
Image<Gray, byte> toErode = new Image<Gray, byte>(path+ "toErode.png");
for(int i =1;i<4;i++)
{
Mat element = CvInvoke.GetStructuringElement(ElementShape.Rectangle, new Size((int)(longestHorLine / i), 3), new Point(-1, -1));
CvInvoke.Erode(toErode, toErode, element, new Point(-1, -1), i, BorderType.Default, new MCvScalar(0));
toErode.Save(path + "res"+i+".png");
}
Which produces the following outputs: res1.png ,res2.png and
res3.png

Body recognition in EmguCV/OpenCV (Tracking person in video)

I am trying to recognize the person in video (not by his face but by his body). What I have done so far now is to find the HOG,HS and RGB histograms of a person and compare it with all other person to find him.
I am using EmguCV but OpenCV's help will also be appreciated.
HOG is Calculated using
Size imageSize = new Size(64, 16);
Size blockSize = new Size(16, 16);
Size blockStride = new Size(16, 8);
Size cellSize = new Size(8, 8);
HOGDescriptor hog = new HOGDescriptor(imageSize, blockSize, blockStride, cellSize);
float[] hogs = hog.Compute(image);
Code to Calculate HS Histograms (Same method is used for RGB)
Image<Gray, byte>[] channels = hsvImage.Copy().Split();
Image<Gray, byte> hue = channels[0];
Image<Gray, byte> sat = channels[1];
dh.Calculate<byte>(new Image<Gray, byte>[] { hue }, true, null);
dh2.Calculate<byte>(new Image<Gray, byte>[] { sat }, true, null);
float[] huehist = dh.GetBinValues();
float[] sathist = dh2.GetBinValues();
Calculating distance of 2 histograms using
double distance = 0;
for (int i = 0; i < hist1.Length; i++)
{
distance += Math.Abs(hist1[i] - hist2[i]);
}
return distance;
What is happening
I am trying to track a selected person from video feed. and the person can move from camera to camera.
The body of personA is extracted from the video frame, whose HOG,HS,RGB histograms are calculated and stored... then from next frame the histograms of all detected persons are calculated and matched with the histograms of personA the most matched histogram (with minimum distance) is considered as the same person (personA)... so it is continued to track that person...
Problem
Accuracy is not good (sometimes it tells 2 people, with very different colored cloths, same)
Suggestions
What should I change/remove
Should I calculate histograms using CvInvoke.CalcHist(...); instead of dense histograms for HS and RGB
Should I normalize histograms before calculating distances.
Is this normalization method good? (every value minus mean of array)
Or should I try something else.
Any kind of help/suggestion will be HIGHLY APPRECIATED if any more info is needed then please comment.
Thanks,
I am also working on the same project, we have same idea of work, i have solutions for this problem.
Solution 1:
after detection of the person crop the detected person extract features, save those features, next them time you wish to track the person extract feature form the frame compare them, I have wrote the whole algorithm
Solution 2
(incase you want to speed up) find the region of the person convert to binary save edges convert the whole frame to binary, find human body region
I have find other tricks for accuracy please contact me on email i have problem writing code we might work together find the best solution

Create Shape from Lines 2D c#

I have a project with a graphic object called GraphicsLine. What it does is simply draw line on every mousedown and stop on every mouseup, nothing complicated. It stores coordinates for the start and the end of the line (x,y). Now what I want to know is whenever a shape is created. For example, you create 4 lines that forms a square, I want to be able to run an algorithm that can tell me that there is a square in the drawing.
Note that the shape can be anything that is "closed". Not only square, rectangle or triangle.
The goal of this is to calculate the area of the created shapes.
Is there something that already exists for doing this? I've been struggling to find something that could fit my needs.
EDIT 1:
I added some additionnal information :
Lines are either "cliped" to another line start or end point or they are not. There is no close closure, it is on the same point or not closed at all. 1 line can be used in multiple shapes.
EDIT 2 :
So basically, I want something that can give me an array of "GraphicsLine" that forms a shape. So if we have 6 lines in the drawing but 4 of them forms a square, I want something that returns those 4 lines so I can create another object from it.
Thanks in advance.
Please check this question How do I calculate the area of a 2d polygon? it is probably what you need, you just have to port it to C# :)
Edit: from #chmike answer:
Where x and y are the arrays of coordinates
var x = [10,10,20,20];
var y = [10,20,20,10];
var n = x.Length;
x[n] = x[0];
x[n+1] = x[1];
y[n] = y[0];
y[n+1] = y[1];
// compute area
int area = 0;
for(var i = 1; i <= n; ++i ) {
area += x[i]*( y[i+1] - y[i-1] );
}
Console.Write(area /= 2);
Take a look at this tutorial of AForge.NET Shape Checker
If your GraphicsLine object is drawing on a PictureBox or if you can convert that object to a bitmap, you can then run the code below.
You can easily try detection of quadrilaterals, this code here will actually highlight the detected objects, you do change the loop and make it do whatever you want instead:
// if you are using a PictureBox to draw the shapes, then convert it to a bitmap
Bitmap bitmap = new Bitmap(pictureBox1.Image)
// locate objects using blob counter
BlobCounter blobCounter = new BlobCounter( );
blobCounter.ProcessImage( bitmap );
Blob[] blobs = blobCounter.GetObjectsInformation( );
// create Graphics object to draw on the image and a pen
Graphics g = Graphics.FromImage( bitmap );
Pen bluePen = new Pen( Color.Blue, 2 );
// check each object and draw circle around objects, which are recognized as circles
for ( int i = 0, n = blobs.Length; i < n; i++ )
{
List<IntPoint> edgePoints = blobCounter.GetBlobsEdgePoints( blobs[i] );
List<IntPoint> corners = PointsCloud.FindQuadrilateralCorners( edgePoints );
g.DrawPolygon( bluePen, ToPointsArray( corners ) );
}
bluePen.Dispose( );
g.Dispose( );
I know it is 2 years + later, but I found a way with a recursive function to know when the shapes are "closed". You start from any points of the last drawed line, then you check if the other point is connected to another line. You do this until you reach the starting point. I save all the lines into another class called Polygon. This way, they keep all the lines with the start and finish that forms the polygon. Then to calculate the area, I do as Eduardo Cobuci said in his answer.
Hope this helps.

How to detect and count a spiral's turns

I need to detect a spiral shaped spring and count its coil turns.
I have tried as follows:
Image<Bgr, Byte> ProcessImage(Image<Bgr, Byte> img)
{
Image<Bgr, Byte> imgClone = new Image<Bgr,byte>( img.Width, img.Height);
imgClone = img.Clone();
Bgr bgrRed = new Bgr(System.Drawing.Color.Red);
#region Algorithm 1
imgClone.PyrUp();
imgClone.PyrDown();
imgClone.PyrUp();
imgClone.PyrDown();
imgClone.PyrUp();
imgClone.PyrDown();
imgClone._EqualizeHist();
imgClone._Dilate(20);
imgClone._EqualizeHist();
imgClone._Erode(10);
imgClone.PyrUp();
imgClone.PyrDown();
imgClone.PyrUp();
imgClone.PyrDown();
imgClone.PyrUp();
imgClone.PyrDown();
imgClone._EqualizeHist();
imgClone._Dilate(20);
imgClone._EqualizeHist();
imgClone._Erode(10);
Image<Gray, Byte> imgCloneGray = new Image<Gray, byte>(imgClone.Width, imgClone.Height);
CvInvoke.cvCvtColor(imgClone, imgCloneGray, Emgu.CV.CvEnum.COLOR_CONVERSION.CV_BGR2GRAY);
imgCloneGray = imgCloneGray.Canny(c_thresh, c_threshLink);//, (int)c_threshSize);
Contour<System.Drawing.Point> pts = imgCloneGray.FindContours(Emgu.CV.CvEnum.CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_SIMPLE, Emgu.CV.CvEnum.RETR_TYPE.CV_RETR_EXTERNAL);
CvInvoke.cvCvtColor(imgCloneGray, imgCloneYcc, Emgu.CV.CvEnum.COLOR_CONVERSION.CV_GRAY2BGR);
if (null != pts)
{
imgClone.Draw(pts, bgrRed, 2);
imgClone.Draw(pts.BoundingRectangle, bgrRed, 2);
}
#endregion
return imgClone;
}
I am some how able to get the spring but how to get the counts. I am looking for algorithms.
I am currently not looking for speed optimization.
This is similar like counting fingers. Spring spiral is very thin to get using contour. What else can be done. http://www.luna-arts.de/others/misc/HandsNew.zip
You have a good final binarization over there, but it looks like to be too restricted to this single case. I would do a relatively simpler, but probably more robust, preprocessing to allow a relatively good binarization. From Mathematical Morphology, there is a transform called h-dome, which is used to remove irrelevant minima/maxima by suppressing minima/maxima of height < h. This operation might not be readily available in your image processing library, but it is not hard to implement it. To binarize this preprocessed image I opted for Otsu's method, since it is automatic and statistically optimal.
Here is the input image after h-dome transformations, and the binary image:
Now, to count the number of "spiral turns" I did something very simple: I split the spirals so I can count them as connected components. To split them I did a single morphological opening with a vertical line, followed by a single dilation by an elementary square. This produces the following image:
Counting the components gives 15. Since you have 13 of them that are not too close, this approach counted them all correctly. The groups at left and right were counted as a single one.
The full Matlab code used to do these steps:
f = rgb2gray(imread('http://i.stack.imgur.com/i7x7L.jpg'));
% For this image, the two next lines are optional as they will to lead
% basically the same binary image.
f1 = imhmax(f, 30);
f2 = imhmin(f1, 30);
bin1 = ~im2bw(f2, graythresh(f2));
bin2 = bwmorph(imopen(bin1, strel('line', 15, 90)), 'dilate');

Invert a non filled Geometry

For some kind of mask dialog I want to be able to invert a geometry in C#. For example I would like to invert a rectange. I've got this working for filled rectangles but the same doesn't work for non filled ones.
For example if I have this rectangle on a canvas:
And I invert this rectangle with the following code:
RectangleGeometry line = new RectangleGeometry(_myRectangle);
RectangleGeometry geo = new RectangleGeometry(_myCanvasRectangle);
PathGeometry intersect = Geometry.Combine(line, geo, GeometryCombineMode.Xor, null);
drawingContext.DrawGeometry(
new SolidColorBrush(Color.FromArgb(99, _myObjectColor.R, _myObjectColor.G, _myObjectColor.B)),
new Pen(new SolidColorBrush(_myObjectColor), _myActualLineWidth),
intersect
);
I get the following result (where the gray region is the filled region)
Does anybody how I could achieve a result where only the rectangle (the black line in the first image) is spared and the rest is returned (filled with gray)?
Thanks guys!
So I found the solution myself:
It seems geometries under C# are always filled "shapes". But you can get the outline (even with desired stroke thickness !) by using the GetWidenedPathGeometry method!
My example looks like this:
RectangleGeometry outerRect = new RectangleGeometry(_myRectangle);
RectangleGeometry geo = new RectangleGeometry(_myCanvasRectangle);
PathGeometry outerRectLine = outerRect.GetWidenedPathGeometry(new Pen(new SolidColorBrush(Colors.White), _myActualLineWidth));
PathGeometry intersect = Geometry.Combine(geo, outerRectLine, GeometryCombineMode.Exclude, null);
drawingContext.DrawGeometry(
new SolidColorBrush(System.Windows.Media.Color.FromArgb(99, _myObjectColor.R, _myObjectColor.G, _myObjectColor.B)),
new System.Windows.Media.Pen(new SolidColorBrush(Colors.White), ActualLineWidth),
intersect
);
Hope this helps someone else!

Categories

Resources