تشخیص اندازه و برش خودکار تصویر در یک عکس اسکن شده

سلام وقت همگی به خیر
دوستان میخواستم بدونم آیا راهی وجود داره که بشه قسمتی از یک عکس اسکن شده که تصویر مورد نظر در اون وجود داره رو از قسمت های سفید تشخیص و برش داد ؟
مثلا در عکس زیر بتونه تصویر کارت ملی رو در صفحه تشخیص و برش بده :


attachment.php


خیلی ممنونم
 

پیوست ها

  • Capture2.PNG
    Capture2.PNG
    153 کیلوبایت · بازدیدها: 9

the_king

مدیرکل انجمن
سلام وقت همگی به خیر
دوستان میخواستم بدونم آیا راهی وجود داره که بشه قسمتی از یک عکس اسکن شده که تصویر مورد نظر در اون وجود داره رو از قسمت های سفید تشخیص و برش داد ؟
مثلا در عکس زیر بتونه تصویر کارت ملی رو در صفحه تشخیص و برش بده :


خیلی ممنونم
صد البته، اگر منظورتون با زبان #C ئه با چند تا حلقه می توانید لبه های کادر مستطیل رو تشخیص دهید و Crop کنید. البته اگر سرعت خیلی براتون ملاک نباشه تغییر رنگ زمینه به شفاف و چرخاندن کادر کج و ... هم عملی است.
متد باید tolerance داشته باشه تا نویز های تصویر رو جزء موضوع حساب نکنه.

کد:
        private Image [B][COLOR="#0000FF"]CropImage[/COLOR][/B](Image image, Color background, Padding margin, double tolerance)
        {
            var bmp = (Bitmap)image;
            var factorY = Math.Max((bmp.Height - margin.Vertical) / 20, 1);
            var factorX = Math.Max((bmp.Width - margin.Horizontal) / 20, 1);
            int x1, x2, y1, y2;
            var finish = false;
            for (x1 = margin.Left; (x1 < bmp.Width - margin.Right) && (finish == false); x1++)
            {
                for (int y = margin.Top; y < bmp.Height - margin.Bottom; y += factorY)
                {
                    if (Tolerance(bmp.GetPixel(x1, y), background) > tolerance)
                    {
                        finish = true;
                        break;
                    }
                }
            }
            finish = false;
            for (x2 = bmp.Width - margin.Right; (x2 > margin.Left) && (finish == false); x2--)
            {
                for (int y = margin.Top; y < bmp.Height - margin.Bottom; y += factorY)
                {
                    if (Tolerance(bmp.GetPixel(x2, y), background) > tolerance)
                    {
                        finish = true;
                        break;
                    }
                }
            }
            finish = false;
            for (y1 = margin.Top; (y1 < bmp.Height - margin.Bottom) && (finish == false); y1++)
            {
                for (int x = margin.Left; x < bmp.Width - margin.Right; x += factorX)
                {
                    if (Tolerance(bmp.GetPixel(x, y1), background) > tolerance)
                    {
                        finish = true;
                        break;
                    }
                }
            }
            finish = false;
            for (y2 = bmp.Height - margin.Bottom; (y2 > margin.Top) && (finish == false); y2--)
            {
                for (int x = margin.Left; x < bmp.Width - margin.Right; x += factorX)
                {
                    if (Tolerance(bmp.GetPixel(x, y2), background) > tolerance)
                    {
                        finish = true;
                        break;
                    }
                }
            }
            var rect = new Rectangle(x1 - 1, y1 - 1, x2 - x1 + 3, y2 - y1 + 3);
            var newBmp = new Bitmap(rect.Width, rect.Height);
            using (var g = Graphics.FromImage(newBmp))
            {
                g.DrawImage(bmp, new Rectangle(0, 0, rect.Width, rect.Height), rect, GraphicsUnit.Pixel);
            }
            return newBmp;
        }

        private double Tolerance(Color a, Color b)
        {
            return Math.Sqrt(Math.Min(Math.Pow((int)a.R - b.R, 2) + Math.Pow((int)a.G - b.G, 2) + Math.Pow((int)a.B - b.B, 2), 65025.0)) / 255.0;
        }

مثلا :
کد:
            var img = [B][COLOR="#0000FF"]CropImage[/COLOR][/B](image, Color.White, new Padding(20, 20, 20, 20), 0.1);

پارامتر ها به ترتیب تصویر منبعی که قراره Crop بشه و رنگ زمینه دور تصویر و حاشیه ای است که دور کادر تصویر باید نادیده گرفته بشه و tolerance ئه که هر چقدر زیادش کنید نویز های بیشتری رو پوشش میده اما
دقت کنید که با زیاد کردن tolerance رنگ های نزدیک به زمینه رو جزء موضوع حساب نخواهد کرد.
به عنوان margin اگر از Padding.Empty استفاده کنید هیچ کادری در دور تصویر رو نادیده نخواهد گرفت.
 
صد البته، اگر منظورتون با زبان #C ئه با چند تا حلقه می توانید...
عرض سلام و ادب
جناب the_king واقعا ازتون ممنونم، کدی که دادید فوق العادست.
من سایت های زیادی (stackoverflow, codeproject, msdn,...) رو گشتم اما بهترین پاسخ رو از شما گرفتم.
چند تا سوال داشتم از خدمتتون...
من یه عکس رو که خروجی یک اسکنر متوسط بود، به این برنامه دادم و در نهایت تونستم با tolerance = 0.3 به نتیجه مطلوب برسم. اما مساله اینه که میخوام پس از تحویل برنامه به مشتری، در صورت تعویض اسکنر، برنامه به مشکل نخوره. یعنی اگر اسکنر جدید ضعیف تر از اسکنر قبلی بود و عکس هاش نویزهای بیشتری داشتن برنامه درست کار کنه. حالا با توجه به وضعیت اسکنرهای موجود در ایران و اینکه این برنامه قراره فقط کارت شناسایی (کارت ملی، شناسنامه،..) رو اسکن بکنه، بهترین tolerance از نظر شما چیه ؟
در ضمن زمانی که Padding.Empty رو به عنوان margin به برنامه میدم ارور زیر رو نشون میده ولی با new Padding(20, 20, 20, 20) جواب میگیرم. مشکل از کجاست ؟
خیلی ممنونم



attachment.php
 

پیوست ها

  • Error.JPG
    Error.JPG
    100 کیلوبایت · بازدیدها: 4

the_king

مدیرکل انجمن
عرض سلام و ادب
جناب the_king واقعا ازتون ممنونم، کدی که دادید فوق العادست.
من سایت های زیادی (stackoverflow, codeproject, msdn,...) رو گشتم اما بهترین پاسخ رو از شما گرفتم.
چند تا سوال داشتم از خدمتتون...
من یه عکس رو که خروجی یک اسکنر متوسط بود، به این برنامه دادم و در نهایت تونستم با tolerance = 0.3 به نتیجه مطلوب برسم. اما مساله اینه که میخوام پس از تحویل برنامه به مشتری، در صورت تعویض اسکنر، برنامه به مشکل نخوره. یعنی اگر اسکنر جدید ضعیف تر از اسکنر قبلی بود و عکس هاش نویزهای بیشتری داشتن برنامه درست کار کنه. حالا با توجه به وضعیت اسکنرهای موجود در ایران و اینکه این برنامه قراره فقط کارت شناسایی (کارت ملی، شناسنامه،..) رو اسکن بکنه، بهترین tolerance از نظر شما چیه ؟
در ضمن زمانی که Padding.Empty رو به عنوان margin به برنامه میدم ارور زیر رو نشون میده ولی با new Padding(20, 20, 20, 20) جواب میگیرم. مشکل از کجاست ؟
خیلی ممنونم



attachment.php

Tolerance چیزی نیست که بشه روی یک عدد ثابت تنظیم اش کرد و ضمانت کنیم که در اون مقدار همیشه درست عمل می کنه، در صورت امکان برای کاربر برنامه تون امکان تغییرش رو بدید.
ببخشید، اشکال از کد دو تا حلقه بود که خطا میده، یک پیکسل فراتر از محدوده رو بررسی می کنه. اون دو تا حلقه یک مورد 1 - و یک مورد = کم داره.
کد:
            for (x2 = bmp.Width - margin.Right [B][COLOR="#0000FF"][SIZE=3]- 1[/SIZE][/COLOR][/B]; (x2 >[B][COLOR="#0000FF"][SIZE=3]=[/SIZE][/COLOR][/B] margin.Left) && (finish == false); x2--)

کد:
            for (y2 = bmp.Height - margin.Bottom [B][COLOR="#0000FF"][SIZE=3]- 1[/SIZE][/COLOR][/B]; (y2 >[B][COLOR="#0000FF"][SIZE=3]=[/SIZE][/COLOR][/B] margin.Top) && (finish == false); y2--)
 

جدیدترین ارسال ها

بالا