Как найти печатный документ на изображенииC#

Место общения программистов C#
Ответить
Anonymous
 Как найти печатный документ на изображении

Сообщение Anonymous »

Изображение содержит отдельный документ, напечатанный в белой бумаге. Background of image can be different.
Tried to get document using code from https://scanbot.io/techblog/document-ed ... th-opencv/ with OpenCvsharp (https://github.com/shimat/opencvsharp) by finding biggest rectangle using C# code

Код: Выделить всё

  using Mat src = Cv2.ImRead("myimage.jpg", ImreadModes.Color);
var result = WarpToTopDown(src);

static Mat WarpToTopDown(Mat src) {
double scale = 900.0 / Math.Max(src.Rows,src.Cols);
Mat small = new();
Cv2.Resize(src,small,new Size((int)(src.Cols * scale),(int)(src.Rows * scale)));
Mat gray = new();
Cv2.CvtColor(small,gray,ColorConversionCodes.BGR2GRAY);

Mat blurred = new();
Cv2.GaussianBlur(gray,blurred,new Size(5,5),0);
Mat edges = new();
Cv2.Canny(blurred,edges,50,150);
Cv2.Dilate(edges,edges,Cv2.GetStructuringElement(MorphShapes.Rect,new Size(3,3)));
Cv2.FindContours(edges,out Point[][]? contours,out _,
RetrievalModes.External,ContourApproximationModes.ApproxSimple);

contours = [.. contours.OrderByDescending(cnt => Cv2.ContourArea(cnt))];
Point2f[]? quad = null;
foreach(Point[]? cnt in contours.Take(10)) {
double peri = Cv2.ArcLength(cnt,true);
Point[] approx = Cv2.ApproxPolyDP(cnt,0.02 * peri,true);
if(approx.Length == 4) {
quad = approx.Select(p => new Point2f(p.X / (float)scale,p.Y / (float)scale)).ToArray();
break;
}
}

if(quad is null) {
thow new Exception("no document");
}

Point2f[] ordered = OrderQuad(quad);
float widthA = Distance(ordered[2],ordered[3]);
float widthB = Distance(ordered[1],ordered[0]);
int maxW = (int)Math.Max(widthA,widthB);
float heightA = Distance(ordered[1],ordered[2]);
float heightB = Distance(ordered[0],ordered[3]);
int maxH = (int)Math.Max(heightA,heightB);

Point2f[] dst = [new Point2f(0,0),
new Point2f(maxW - 1,0),
new Point2f(maxW - 1,maxH - 1),
new Point2f(0,maxH - 1)];
Mat M = Cv2.GetPerspectiveTransform(ordered,dst);
Mat warped = new();
Cv2.WarpPerspective(src,warped,M,new Size(maxW,maxH));
return warped;
}

static Point2f[] OrderQuad(Point2f[] pts) {
Point2f[] ordered = new Point2f[4];
float[] sum = [.. pts.Select(p => p.X + p.Y)];
float[] diff = [.. pts.Select(p => p.X - p.Y)];
ordered[0] = pts[Array.IndexOf(sum,sum.Min())]; // tl
ordered[2] = pts[Array.IndexOf(sum,sum.Max())]; // br
ordered[1] = pts[Array.IndexOf(diff,diff.Max())]; // tr
ordered[3] = pts[Array.IndexOf(diff,diff.Min())]; // bl
return ordered;
}

static float Distance(Point2f a,Point2f b) => (float)Math.Sqrt(Math.Pow(a.X - b.X,2) + Math.Pow(a.Y - b.Y,2));
< /code>
Но это возвращает целое изображение. В Foreach Check < /p>
  if(approx.Length == 4) {
Если true для первого контура, который является целым изображением и, следовательно, возвращается целое изображение.
для изображения


Подробнее здесь: https://stackoverflow.com/questions/797 ... t-in-image
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»