ওপেনসিভি সি ++ / ওবজে-সি: কাগজ / স্কয়ার সনাক্তকরণের একটি শীট সনাক্ত করা


178

আমি আমার পরীক্ষার অ্যাপ্লিকেশনটিতে ওপেনসিভি স্কোয়ার-সনাক্তকরণ উদাহরণটি সফলভাবে প্রয়োগ করেছি, তবে এখন আউটপুট ফিল্টার করা দরকার, কারণ এটি বেশ অগোছালো - বা আমার কোডটি ভুল?

আমি স্কিউ রিডাকশন (মত জন্য কাগজ চারটি কোণ পয়েন্টে আগ্রহী যে ) এবং আরও প্রক্রিয়াকরণের ...

ইনপুট আউটপুট: ইনপুট আউটপুট

আসল চিত্র:

ক্লিক

কোড:

double angle( cv::Point pt1, cv::Point pt2, cv::Point pt0 ) {
    double dx1 = pt1.x - pt0.x;
    double dy1 = pt1.y - pt0.y;
    double dx2 = pt2.x - pt0.x;
    double dy2 = pt2.y - pt0.y;
    return (dx1*dx2 + dy1*dy2)/sqrt((dx1*dx1 + dy1*dy1)*(dx2*dx2 + dy2*dy2) + 1e-10);
}

- (std::vector<std::vector<cv::Point> >)findSquaresInImage:(cv::Mat)_image
{
    std::vector<std::vector<cv::Point> > squares;
    cv::Mat pyr, timg, gray0(_image.size(), CV_8U), gray;
    int thresh = 50, N = 11;
    cv::pyrDown(_image, pyr, cv::Size(_image.cols/2, _image.rows/2));
    cv::pyrUp(pyr, timg, _image.size());
    std::vector<std::vector<cv::Point> > contours;
    for( int c = 0; c < 3; c++ ) {
        int ch[] = {c, 0};
        mixChannels(&timg, 1, &gray0, 1, ch, 1);
        for( int l = 0; l < N; l++ ) {
            if( l == 0 ) {
                cv::Canny(gray0, gray, 0, thresh, 5);
                cv::dilate(gray, gray, cv::Mat(), cv::Point(-1,-1));
            }
            else {
                gray = gray0 >= (l+1)*255/N;
            }
            cv::findContours(gray, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE);
            std::vector<cv::Point> approx;
            for( size_t i = 0; i < contours.size(); i++ )
            {
                cv::approxPolyDP(cv::Mat(contours[i]), approx, arcLength(cv::Mat(contours[i]), true)*0.02, true);
                if( approx.size() == 4 && fabs(contourArea(cv::Mat(approx))) > 1000 && cv::isContourConvex(cv::Mat(approx))) {
                    double maxCosine = 0;

                    for( int j = 2; j < 5; j++ )
                    {
                        double cosine = fabs(angle(approx[j%4], approx[j-2], approx[j-1]));
                        maxCosine = MAX(maxCosine, cosine);
                    }

                    if( maxCosine < 0.3 ) {
                        squares.push_back(approx);
                    }
                }
            }
        }
    }
    return squares;
}

সম্পাদনা 17/08/2012:

চিত্রটিতে চিহ্নিত স্কোয়ারগুলি আঁকতে এই কোডটি ব্যবহার করুন:

cv::Mat debugSquares( std::vector<std::vector<cv::Point> > squares, cv::Mat image )
{
    for ( int i = 0; i< squares.size(); i++ ) {
        // draw contour
        cv::drawContours(image, squares, i, cv::Scalar(255,0,0), 1, 8, std::vector<cv::Vec4i>(), 0, cv::Point());

        // draw bounding rect
        cv::Rect rect = boundingRect(cv::Mat(squares[i]));
        cv::rectangle(image, rect.tl(), rect.br(), cv::Scalar(0,255,0), 2, 8, 0);

        // draw rotated rect
        cv::RotatedRect minRect = minAreaRect(cv::Mat(squares[i]));
        cv::Point2f rect_points[4];
        minRect.points( rect_points );
        for ( int j = 0; j < 4; j++ ) {
            cv::line( image, rect_points[j], rect_points[(j+1)%4], cv::Scalar(0,0,255), 1, 8 ); // blue
        }
    }

    return image;
}


1
আমি মনে করি আপনি যদি আরও উপযুক্ত মনে করেন তবে আপনি কাগজের একটি শীট সনাক্তকরণের মতো কোনও কিছুর জন্য প্রশ্নের শিরোনাম সামঞ্জস্য করতে পারেন ।
করালফিলিপ

1
@ মূসগুম্মি আমি একই কার্যকারিতাটি দেখতে চাই যা আপনি বাস্তবায়ন করেছেন অর্থাৎ "ধরা পড়া চিত্র / নথির কর্নারগুলি সনাক্ত করুন" H আপনি কীভাবে এটি অর্জন করেছেন? আমি কি আমার আইফোন অ্যাপ্লিকেশনটির মধ্যে ওপেনসিভি ব্যবহার করতে সক্ষম হব? দয়া করে আমাকে এটির জন্য আরও কিছু ভাল উপায়ের পরামর্শ দিন ..
অজয় শর্মা

1
আপনি কি কখনও ওপেনসিভি দিয়ে কিছু করেছেন? কোন আবেদন কি আদৌ?
করলফিলিপ

6
এটি লক্ষণীয় যে, সিএনভিআরটিআর_আরএএনআরএল পতাকাটি একটি বন্ধ আকারের অভ্যন্তরে সমস্ত সংশ্লেষ প্রত্যাখ্যান করার জন্য গণনাগুলি সন্ধান করার সময় ব্যবহার করা যেতে পারে।
mehfoos yacoob

উত্তর:


162

এটি স্ট্যাকওভারফ্লোতে একটি পুনরাবৃত্তিযোগ্য বিষয় এবং যেহেতু আমি কোনও প্রাসঙ্গিক বাস্তবায়ন পেতে অক্ষম হয়েছি আমি চ্যালেঞ্জটি গ্রহণ করার সিদ্ধান্ত নিয়েছি।

আমি ওপেনসিভিতে উপস্থিত স্কোয়ার্স ডেমোতে কিছু পরিবর্তন করেছি এবং ফলাফলের সি ++ কোড নীচে ছবিতে কাগজের একটি শীট সনাক্ত করতে সক্ষম:

void find_squares(Mat& image, vector<vector<Point> >& squares)
{
    // blur will enhance edge detection
    Mat blurred(image);
    medianBlur(image, blurred, 9);

    Mat gray0(blurred.size(), CV_8U), gray;
    vector<vector<Point> > contours;

    // find squares in every color plane of the image
    for (int c = 0; c < 3; c++)
    {
        int ch[] = {c, 0};
        mixChannels(&blurred, 1, &gray0, 1, ch, 1);

        // try several threshold levels
        const int threshold_level = 2;
        for (int l = 0; l < threshold_level; l++)
        {
            // Use Canny instead of zero threshold level!
            // Canny helps to catch squares with gradient shading
            if (l == 0)
            {
                Canny(gray0, gray, 10, 20, 3); // 

                // Dilate helps to remove potential holes between edge segments
                dilate(gray, gray, Mat(), Point(-1,-1));
            }
            else
            {
                    gray = gray0 >= (l+1) * 255 / threshold_level;
            }

            // Find contours and store them in a list
            findContours(gray, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE);

            // Test contours
            vector<Point> approx;
            for (size_t i = 0; i < contours.size(); i++)
            {
                    // approximate contour with accuracy proportional
                    // to the contour perimeter
                    approxPolyDP(Mat(contours[i]), approx, arcLength(Mat(contours[i]), true)*0.02, true);

                    // Note: absolute value of an area is used because
                    // area may be positive or negative - in accordance with the
                    // contour orientation
                    if (approx.size() == 4 &&
                            fabs(contourArea(Mat(approx))) > 1000 &&
                            isContourConvex(Mat(approx)))
                    {
                            double maxCosine = 0;

                            for (int j = 2; j < 5; j++)
                            {
                                    double cosine = fabs(angle(approx[j%4], approx[j-2], approx[j-1]));
                                    maxCosine = MAX(maxCosine, cosine);
                            }

                            if (maxCosine < 0.3)
                                    squares.push_back(approx);
                    }
            }
        }
    }
}

এই প্রক্রিয়াটি কার্যকর হওয়ার পরে, কাগজের পত্রকটি সবচেয়ে বড় বর্গ হবে vector<vector<Point> >:

ওপেনসিভি পেপার শিট সনাক্তকরণ

আমি আপনাকে বৃহত্তম স্কোয়ার সন্ধান করতে ফাংশনটি লিখতে দিচ্ছি। ;)


4
এজন্য আমি উত্স নিয়ন্ত্রণ ব্যবহার করি। কোডটিতে ক্ষুদ্রতম দুর্ঘটনা পরিবর্তন খুব সহজেই আবিষ্কার করা যায়। যদি আপনি কিছু পরিবর্তন করেন না, অন্য চিত্রগুলির সাথে পরীক্ষার চেষ্টা করুন এবং অবশেষে পুনরায় সংকলন করুন / ওপেনসিভি পুনরায় ইনস্টল করুন।
করলফিলিপ

2
ওপেনসিভি সমস্ত প্ল্যাটফর্মের জন্য একরকম (উইন / লিনাক্স / ম্যাক / আইফোন / ...)। পার্থক্যটি হ'ল কেউ কেউ ওপেনসিভির জিপিইউ মডিউল সমর্থন করে না। আপনি কি ইতিমধ্যে আইওএসের জন্য ওপেনসিভি তৈরি করেছেন ? আপনি কি এটি পরীক্ষা করতে পেরেছিলেন? আমার মনে হয় আরও কিছু উন্নত করার চেষ্টা করার আগে আপনার এই উত্তরগুলির দরকার উত্তর। শিশুর পদক্ষেপ!
করলফিলিপ

1
@ কার্লফিলিপ আমি এই কোডটি পরীক্ষা করেছি এবং আমি কাগজটি স্পষ্টভাবে সনাক্ত করতে সক্ষম হয়েছি, তবে এটি এত বেশি সময় নেয়। কোডটি কি আসলেই ভারী? SayText নামে একটি অ্যাপ রয়েছে যেখানে একটি ভিডিও স্ট্রিম থেকে রিয়েল-টাইমে এই সনাক্তকরণ ঘটে। এই কোডটি রিয়েল-টাইমের জন্য অযৌক্তিক হবে, আমি ঠিক আছি?
আল্যান্ডালুসি

1
সম্ভবত। এটি একাডেমিক উত্তর, শিল্পের জন্য খুব ব্যবহারিক নয়। এখানে অবস্থিত কাউন্টারটির সংজ্ঞা দিয়ে শুরু করে আপনি চেষ্টা করতে পারেন এমন সমস্ত ধরণের অপ্টিমাইজেশন রয়েছে for (int c = 0; c < 3; c++)যা চিত্রের প্রতিটি চ্যানেলে পুনরাবৃত্তি করতে দায়বদ্ধ। উদাহরণস্বরূপ, আপনি এটি কেবল একটি চ্যানেলে পুনরাবৃত্তি করতে সেট করতে পারেন :) ভোট আপ করতে ভুলবেন না।
করলফিলিপ

3
@ সাইলেন্টপ্রো angle()একটি সহায়ক ফাংশন । উত্তরে বর্ণিত হিসাবে, এই কোডটি ওপেনসিভিতে উপস্থিত নমুনা / সিপিপি / স্কোয়ারস সিপিপি এর উপর ভিত্তি করে ।
করলফিলিপ

40

অন্য কোনও প্রয়োজনীয়তা নির্দিষ্ট না করা না হলে আমি কেবল আপনার রঙিন চিত্রটিকে গ্রেস্কেল রূপান্তর করব এবং কেবল এটির সাথেই কাজ করব (3 টি চ্যানেলে কাজ করার দরকার নেই, ইতিমধ্যে বিপরীতে উপস্থিত উপস্থিতি খুব বেশি)। এছাড়াও, আকার পরিবর্তন সংক্রান্ত কিছু নির্দিষ্ট সমস্যা না থাকলে আমি আপনার চিত্রগুলির একটি ডাউন স্কেল সংস্করণ নিয়ে কাজ করব, কারণ সেগুলি তুলনামূলকভাবে বড় এবং আকারটি সমস্যার সমাধানে কোনও কিছুই যুক্ত করে না। তারপরে, অবশেষে, আপনার সমস্যাটি একটি মিডিয়া ফিল্টার, কিছু বেসিক মোর্ফোলজিকাল সরঞ্জাম এবং পরিসংখ্যান (বেশিরভাগ Otsu প্রান্তিকের জন্য যা ইতিমধ্যে আপনার জন্য সম্পন্ন হয়েছে) দিয়ে সমাধান করা হয়।

আমি আপনার নমুনা চিত্র এবং আমার কাছাকাছি পাওয়া কাগজের শীট দিয়ে অন্য কিছু চিত্র নিয়ে যা পেয়েছি তা এখানে:

এখানে চিত্র বর্ণনা লিখুন এখানে চিত্র বর্ণনা লিখুন

মিডিয়ান ফিল্টারটি, এখন গ্রেস্কেল, চিত্র থেকে ছোটখাট বিবরণ সরাতে ব্যবহৃত হয়। এটি সম্ভবত সাদা রঙের কাগজের অভ্যন্তরে পাতলা রেখাগুলি সরিয়ে ফেলবে, যা ভাল কারণ তখন আপনি ক্ষুদ্র সংযুক্ত উপাদানগুলি শেষ করবেন যা ফেলে দেওয়া সহজ। মিডিয়ানের পরে, একটি রূপচর্চা গ্রেডিয়েন্ট প্রয়োগ করুন (কেবল dilation- erosion) এবং ওতসু দ্বারা ফলাফল বাইনারি করুন। মোড়ফোলজিকাল গ্রেডিয়েন্ট শক্ত প্রান্ত রাখতে একটি ভাল পদ্ধতি, এটি আরও ব্যবহার করা উচিত। তারপরে, যেহেতু এই গ্রেডিয়েন্টটি কনট্যুর প্রস্থকে বাড়িয়ে দেবে, তাই রূপচিকিত্সা পাতলা প্রয়োগ করুন। এখন আপনি ছোট উপাদানগুলি বাতিল করতে পারেন।

এই মুহুর্তে, উপরে ডান চিত্র সহ আমাদের যা রয়েছে তা এখানে রয়েছে (নীল বহুভুজ আঁকার আগে), বামটি প্রদর্শিত হয় না কারণ কেবলমাত্র অবশিষ্ট উপাদানটিই কাগজটি বর্ণনা করছে:

এখানে চিত্র বর্ণনা লিখুন

উদাহরণগুলি দেওয়া, এখন কেবলমাত্র ইস্যুটি বাকি উপাদানগুলির মধ্যে পার্থক্য যা আয়তক্ষেত্রগুলির মতো দেখায় এবং অন্যগুলি যা না দেয়। এটি আকৃতি সমেত উত্তল হলের ক্ষেত্রফল এবং তার সীমানা বাক্সের ক্ষেত্রফলের মধ্যে একটি অনুপাত নির্ধারণের বিষয়; অনুপাত 0.7 এই উদাহরণগুলির জন্য সূক্ষ্মভাবে কাজ করে। এটি এমন ক্ষেত্রে হতে পারে যে আপনাকে কাগজের অভ্যন্তরে থাকা উপাদানগুলিও ফেলে দিতে হবে, তবে এই পদ্ধতিটি ব্যবহার করে এই উদাহরণগুলিতে নয় (তবুও, এই পদক্ষেপটি করা খুব সহজ হওয়া উচিত বিশেষত কারণ এটি সরাসরি ওপেনসিভির মাধ্যমে করা যেতে পারে)।

রেফারেন্সের জন্য, এখানে গাণিতিকের একটি নমুনা কোড রয়েছে:

f = Import["http://thwartedglamour.files.wordpress.com/2010/06/my-coffee-table-1-sa.jpg"]
f = ImageResize[f, ImageDimensions[f][[1]]/4]
g = MedianFilter[ColorConvert[f, "Grayscale"], 2]
h = DeleteSmallComponents[Thinning[
     Binarize[ImageSubtract[Dilation[g, 1], Erosion[g, 1]]]]]
convexvert = ComponentMeasurements[SelectComponents[
     h, {"ConvexArea", "BoundingBoxArea"}, #1 / #2 > 0.7 &], 
     "ConvexVertices"][[All, 2]]
(* To visualize the blue polygons above: *)
Show[f, Graphics[{EdgeForm[{Blue, Thick}], RGBColor[0, 0, 1, 0.5], 
     Polygon @@ convexvert}]]

যদি আরও বিচিত্র পরিস্থিতি থাকে যেখানে কাগজের আয়তক্ষেত্রটি এত ভালভাবে সংজ্ঞায়িত না হয়, বা পদ্ধতিটি এটি অন্য আকারগুলির সাথে বিভ্রান্ত করে - এই পরিস্থিতি বিভিন্ন কারণে ঘটতে পারে তবে একটি সাধারণ কারণ খারাপ চিত্র অর্জন acquisition তবে পূর্ববর্তীটি একত্রিত করার চেষ্টা করুন "উইন্ডোড হাফ ট্রান্সফর্মের উপর ভিত্তি করে আয়তক্ষেত্র সনাক্তকরণ" কাগজে বর্ণিত কাজের সাথে পদক্ষেপগুলি প্রসেস করা।


1
আপনার এবং উপরেরটিটির (যেমন @ কার্লফিলিপের উত্তর) বাস্তবায়নে কোনও বড় পার্থক্য রয়েছে? আমি দুঃখিত আমি দ্রুত চেহারায় কোনও দেখতে পেলাম না (3 টি চ্যানেল -1 চ্যানেল এবং ম্যাথেমেটিকা-ওপেনসিভি ব্যতীত)।
আবিদ রহমান কে

2
@ আবিদআরহমানক হ্যাঁ, আছে .. আমি শুরু করতে ক্যানি ব্যবহার করি না "বেশ কয়েকটি দোর"। অন্যান্য পার্থক্য রয়েছে, তবে আপনার মন্তব্যের সুরে আমার নিজের মন্তব্যে কোনও প্রচেষ্টা করা অর্থহীন বলে মনে হচ্ছে।
এমএমজিপি

1
আমি উভয়কেই প্রথমে প্রান্তগুলি দেখতে পাচ্ছি এবং কোন প্রান্তটি বর্গক্ষেত্র তা নির্ধারণ করুন। প্রান্তগুলি সন্ধানের জন্য, আপনি লোকেরা বিভিন্ন পদ্ধতি ব্যবহার করেন। তিনি ক্যানি ব্যবহার করেন, আপনি কিছু ক্ষয়-ক্ষয় ব্যবহার করেন। এবং "বেশ কয়েকটি চৌম্বক", হতে পারে সে ওপেনসিভি নমুনাগুলি থেকে পেয়েছিল, স্কোয়ারগুলি সন্ধান করতে ব্যবহৃত হত। মূল কথাটি হ'ল, আমি অনুভব করেছি সামগ্রিক ধারণাটি একই। "প্রান্তগুলি সন্ধান করুন এবং স্কোয়ার সনাক্ত করুন"। এবং আমি এটিকে আন্তরিকভাবে জিজ্ঞাসা করেছি, আমার মন্তব্য থেকে আপনি কী "সুর" পেয়েছেন বা আপনি কী বুঝতে পেরেছেন / বুঝতে পেরেছেন তা আমি জানি না। সুতরাং আপনি যদি এই প্রশ্নটি আন্তরিক মনে করেন তবে আমি অন্যান্য পার্থক্যগুলি জানতে চাই। অন্যথায় আমার মন্তব্য বাতিল।
আবিদ রহমান কে

1
@ আবিদআরহমানক অবশ্যই ধারণাটি এক, কার্য একই রকম। মিডিয়ান ফিল্টারিং ব্যবহার করা হচ্ছে, পাতলা হওয়া ব্যবহার করা হচ্ছে, তিনি যেখান থেকে বেশ কয়েকটি চৌম্বকীয় ধারণা নিয়েছিলেন সেদিকে আমার খেয়াল নেই - এটি ঠিক এখানে ব্যবহার করা হয়নি (সুতরাং এটি কীভাবে কোনও পার্থক্য হতে পারে না?), চিত্রটি এখানে পুনরায় আকার দেওয়া হয়েছে, উপাদান পরিমাপ আলাদা। "কিছু প্রসারণ-ক্ষয়" বাইনারি প্রান্ত দেয় না, এর জন্য ওতসু ব্যবহৃত হয়। এটি উল্লেখ করা অর্থহীন, কোডটি এখানে রয়েছে।
মিমজিপি

1
কে। আপনাকে ধন্যবাদ উত্তর পেয়েছি। Concept is the same। (আমি কখনই ম্যাথমেটিকাকে ব্যবহার করি নি, তাই আমি কোডটি বুঝতে পারি না)) এবং আপনি যে পার্থক্যগুলি উল্লেখ করেছেন সেগুলি হ'ল পার্থক্য, তবে কোনও ভিন্ন পদ্ধতির বা প্রধান বিষয় নয়। যদি আপনি এখনও উদাহরণস্বরূপ না করেন তবে এটি দেখুন:
আবিদ রহমান কে

14

ঠিক আছে, আমি দেরি করে ফেলেছি।


আপনার চিত্রটিতে, কাগজটি whiteযখন পটভূমি হয় colored। সুতরাং, কাগজটি Saturation(饱和度)চ্যানেলটি রয়েছে তা সনাক্ত করা ভাল HSV color space। প্রথমে উইকি এইচএসএল_এন্ড_এইচএসভি দেখুন । তারপরে আমি আমার উত্তর থেকে বেশিরভাগ ধারণাকে অনুলিপি করব একটি চিত্রের এই সনাক্তকরণ রঙিন বিভাগে


প্রধান পদক্ষেপ:

  1. পড়ুন BGR
  2. থেকে ইমেজ রূপান্তর bgrকরতে hsvস্থান
  3. এস চ্যানেলটি প্রসারিত করুন
  4. তারপরে কোণগুলি পেতে সর্বাধিক বাহ্যিক কনট্যুর (অথবা করুন Canny, বা HoughLinesআপনার পছন্দ হিসাবে আমি পছন্দ করি findContours) সন্ধান করুন।

এটি আমার ফলাফল:

এখানে চিত্র বর্ণনা লিখুন


পাইথন কোড (পাইথন 3.5 3.5 + ওপেনসিভি 3.3):

#!/usr/bin/python3
# 2017.12.20 10:47:28 CST
# 2017.12.20 11:29:30 CST

import cv2
import numpy as np

##(1) read into  bgr-space
img = cv2.imread("test2.jpg")

##(2) convert to hsv-space, then split the channels
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
h,s,v = cv2.split(hsv)

##(3) threshold the S channel using adaptive method(`THRESH_OTSU`) or fixed thresh
th, threshed = cv2.threshold(s, 50, 255, cv2.THRESH_BINARY_INV)

##(4) find all the external contours on the threshed S
#_, cnts, _ = cv2.findContours(threshed, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cv2.findContours(threshed, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[-2]

canvas  = img.copy()
#cv2.drawContours(canvas, cnts, -1, (0,255,0), 1)

## sort and choose the largest contour
cnts = sorted(cnts, key = cv2.contourArea)
cnt = cnts[-1]

## approx the contour, so the get the corner points
arclen = cv2.arcLength(cnt, True)
approx = cv2.approxPolyDP(cnt, 0.02* arclen, True)
cv2.drawContours(canvas, [cnt], -1, (255,0,0), 1, cv2.LINE_AA)
cv2.drawContours(canvas, [approx], -1, (0, 0, 255), 1, cv2.LINE_AA)

## Ok, you can see the result as tag(6)
cv2.imwrite("detected.png", canvas)

সম্পর্কিত উত্তর:

  1. ওপেনসিভি ব্যবহার করে কোনও চিত্রে রঙিন প্যাচগুলি কীভাবে সনাক্ত করা যায়?
  2. ওপেনসিভি ব্যবহার করে রঙিন পটভূমিতে এজ সনাক্তকরণ
  3. ওপেনসিভি সি ++ / ওবজে-সি: কাগজ / স্কয়ার সনাক্তকরণের একটি শীট সনাক্ত করা
  4. বিভিন্ন ওপেনসিভি সংস্করণে `cv2.findContours` কীভাবে ব্যবহার করবেন?

আমি এস স্পেস ব্যবহার করার চেষ্টা করেছি কিন্তু এখনও সফল হতে পারি নি। : এই দেখুন stackoverflow.com/questions/50699893/...
hchouhan02

3

আপনার যা প্রয়োজন তা হল একটি ঘোরানো আয়তক্ষেত্রের পরিবর্তে চতুর্ভুজRotatedRectআপনাকে ভুল ফলাফল দেবে। এছাড়াও আপনার প্রয়োজন একটি দৃষ্টিকোণ প্রক্ষেপণ।

মূলত যা করা উচিত তা হ'ল:

  • সমস্ত বহুভুজ বিভাগে লুপ করুন এবং প্রায় সমতুল্য সেগুলি সংযুক্ত করুন।
  • এগুলি বাছাই করুন যাতে আপনার 4 টি সর্বাধিক বৃহত্তম রেখাংশ থাকে।
  • এই রেখাগুলি ছেদ করুন এবং আপনার 4 টি খুব সম্ভবত কোণার পয়েন্ট রয়েছে।
  • কোণার পয়েন্ট এবং পরিচিত বস্তুর অনুপাত অনুপাত থেকে জড়ো দৃষ্টিভঙ্গির উপর ম্যাট্রিক্স রূপান্তর করুন।

আমি এমন একটি শ্রেণি প্রয়োগ করেছি Quadrangleযা রূপান্তরকে চতুর্ভুজ করতে কনট্যুরের যত্ন নেয় এবং এটিকে সঠিক দৃষ্টিকোণে রূপান্তরিতও করে।

এখানে একটি কার্যকরী বাস্তবায়ন দেখুন: জাভা ওপেনসিভি কনট্যুরটি আবিষ্কার করছে


1

একবার আপনি নথির বাউন্ডিং বাক্সটি সনাক্ত করে ফেললে, আপনি চিত্রের উপরের-নীচে পাখির চোখের দর্শন পেতে একটি চার-পয়েন্ট দৃষ্টিভঙ্গি রূপান্তর করতে পারেন। এটি স্কিউ সংশোধন করবে এবং কেবলমাত্র পছন্দসই বস্তুকে পৃথক করবে।


ইনপুট চিত্র:

সনাক্ত করা টেক্সট অবজেক্ট

টেক্সট ডকুমেন্টের টপ-ডাউন ভিউ

কোড

from imutils.perspective import four_point_transform
import cv2
import numpy

# Load image, grayscale, Gaussian blur, Otsu's threshold
image = cv2.imread("1.png")
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(gray, (7,7), 0)
thresh = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]

# Find contours and sort for largest contour
cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
cnts = sorted(cnts, key=cv2.contourArea, reverse=True)
displayCnt = None

for c in cnts:
    # Perform contour approximation
    peri = cv2.arcLength(c, True)
    approx = cv2.approxPolyDP(c, 0.02 * peri, True)
    if len(approx) == 4:
        displayCnt = approx
        break

# Obtain birds' eye view of image
warped = four_point_transform(image, displayCnt.reshape(4, 2))

cv2.imshow("thresh", thresh)
cv2.imshow("warped", warped)
cv2.imshow("image", image)
cv2.waitKey()

-1

কাগজের শীট শনাক্ত করা পুরানো স্কুল। আপনি যদি স্কিউ সনাক্তকরণ মোকাবেলা করতে চান তবে আপনি সরাসরি পাঠ্য লাইন সনাক্তকরণের জন্য লক্ষ্য রাখাই ভাল। এটির সাহায্যে আপনি বাম, ডান, উপরে এবং নীচে এক্সট্রিমাস পাবেন। আপনি যদি না চান তবে চিত্রের যে কোনও গ্রাফিকগুলি ত্যাগ করুন এবং তারপরে পাঠ্যলাইন বিভাগে কিছু পরিসংখ্যান করুন যাতে সর্বাধিক উদ্ভূত কোণ পরিসর বা পরিবর্তে কোণ খুঁজে পাওয়া যায়। এভাবেই আপনি একটি ভাল স্কিউ কোণে সঙ্কুচিত হবেন। এখন এর পরে আপনি এই প্যারামিটারগুলি স্কিউ এঙ্গেল এবং এক্সট্রিমাসগুলি ছদ্মবেশে কাটাতে এবং প্রয়োজনীয় চিত্রটি কাটাতে লাগিয়েছেন।

বর্তমান চিত্রের প্রয়োজন হিসাবে, আপনি যদি CV_RETR_LIST এর পরিবর্তে CV_RETR_EXTERNAL ব্যবহার করে থাকেন তবে এটি আরও ভাল।

প্রান্ত সনাক্তকরণের আরেকটি পদ্ধতি হ'ল কাগজের প্রান্তগুলিতে একটি এলোমেলো বনের শ্রেণিবদ্ধকে প্রশিক্ষণ দেওয়া এবং তারপরে প্রান্ত মানচিত্রটি পেতে শ্রেণিবদ্ধ ব্যবহার করে use এটি এখন পর্যন্ত একটি শক্তিশালী পদ্ধতি তবে প্রশিক্ষণ এবং সময় প্রয়োজন।

এলোমেলো বনগুলি কম বৈপরীত্যের পার্থক্যের দৃশ্যের সাথে কাজ করবে উদাহরণস্বরূপ প্রায় সাদা ব্যাকগ্রাউন্ডে সাদা কাগজ।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.