May be anybody know, how i can find document on scanned image? Use OpenCV, C++ or C#! Try find squares, but this not work! Attach picture for example
1 | initial version |
May be anybody know, how i can find document on scanned image? Use OpenCV, C++ or C#! Try find squares, but this not work! Attach picture for example
2 | No.2 Revision |
May be anybody know, how i can find document on scanned image? Use OpenCV, C++ or C#! Try find squares, but this not work! Attach picture for example example, i need crop this red rectangle from picture
3 | No.3 Revision |
May be anybody know, how i can find document on scanned image? Use OpenCV, C++ or C#! Try find squares, but this not work! Attach picture for example, i need crop this red rectangle from picture ` static CvPoint[] FindSquare(IplImage img, CvMemStorage storage) { const int N = 15;//11
CvSize sz = new CvSize(img.Width & -2, img.Height & -2);
IplImage timg = img.Clone(); // make a copy of input image
//Draw frame in begin of image for best square finding near edge of big image
timg.DrawRect(0, 0, timg.Width, timg.Height, CvColor.Black, 2);
IplImage gray = new IplImage(sz, BitDepth.U8, 1);
IplImage pyr = new IplImage(sz.Width / 2, sz.Height / 2, BitDepth.U8, 3);
// create empty sequence that will contain points -
// 4 points per square (the square's vertices)
CvSeq<CvPoint> squares = new CvSeq<CvPoint>(SeqType.Zero, CvSeq.SizeOf, storage);
// select the maximum ROI in the image
// with the width and height divisible by 2
timg.ROI = new CvRect(0, 0, sz.Width, sz.Height);
// down-Scale and upscale the image to filter out the noise
Cv.PyrDown(timg, pyr, CvFilter.Gaussian5x5);
Cv.PyrUp(pyr, timg, CvFilter.Gaussian5x5);
IplImage tgray = new IplImage(sz, BitDepth.U8, 1);
// extract the c-th color plane
timg.COI = 1;
Cv.Copy(timg, tgray, null);
// try several threshold levels
for (int l = 1; l < N; l++)
{
// hack: use Canny instead of zero threshold level.
// Canny helps to catch squares with gradient shading
if (l == 0)
{
// apply Canny. Take the upper threshold from slider
// and set the lower to 0 (which forces edges merging)
Cv.Canny(tgray, gray, 0, Thresh, ApertureSize.Size5);
// dilate canny output to remove potential
// holes between edge segments
Cv.Dilate(gray, gray, null, 1);
}
else
{
// apply threshold if l!=0:
// tgray(x,y) = gray(x,y) < (l+1)*255/N ? 255 : 0
Cv.Threshold(tgray, gray, (l + 1) * 255.0 / N, 255, ThresholdType.Binary);
}
// find contours and store them all as a list
CvSeq<CvPoint> contours;
Cv.FindContours(gray, storage, out contours, CvContour.SizeOf, ContourRetrieval.List, ContourChain.ApproxSimple, new CvPoint(0, 0));
// test each contour
while (contours != null)
{
// approximate contour with accuracy proportional
// to the contour perimeter
CvSeq<CvPoint> result = Cv.ApproxPoly(contours, CvContour.SizeOf, storage, ApproxPolyMethod.DP, contours.ContourPerimeter() * 0.02, false);
// square contours should have 4 vertices after approximation
// relatively large area (to filter out noisy contours)
// and be convex.
// Note: absolute value of an area is used because
// area may be positive or negative - in accordance with the
// contour orientation
if (result.Total == 4 && Math.Abs(result.ContourArea(CvSlice.WholeSeq)) > 1000 && result.CheckContourConvexity())
{
double s = 0;
for (int i = 0; i < 5; i++)
{
// find minimum Angle between joint
// edges (maximum of cosine)
if (i >= 2)
{
double t = Math.Abs(Angle(result[i].Value, result[i - 2].Value, result[i - 1].Value));
s = s > t ? s : t;
}
}
// if cosines of all angles are small
// (all angles are ~90 degree) then write quandrange
// vertices to resultant sequence
if (s < 0.3)
{
for (int i = 0; i < 4; i++)
{
//My squares. Then sort counturs of squares by area
squares.Push(result[i].Value);
}
}
}
// take the next contour
contours = contours.HNext;
}
}`