ওপেনসিভি ব্যবহার করে চিত্রটিতে উপস্থিত সমস্ত পাঠ্যের অবস্থান পান


11

আমার এই চিত্রটিতে এতে পাঠ্য (সংখ্যা এবং বর্ণমালা) রয়েছে। আমি এই চিত্রটিতে উপস্থিত সমস্ত পাঠ্য এবং সংখ্যাগুলির অবস্থান পেতে চাই। এছাড়াও আমি সমস্ত পাঠ্যও বের করতে চাই।

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

আমি কীভাবে কর্ডিনেটের পাশাপাশি আমার চিত্রের সমস্ত পাঠ্য (সংখ্যা এবং বর্ণমালা) পাব? যেমন 10 বি, 44, 16, 38, 22 বি ইত্যাদি


আপনার টেনসরফ্লো সংস্করণটি কী? আপনার সংস্করণটি যদি ২.১ হয় তবে ২.০
জেললেজজ

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

@কারলফিলিপ তাই দুঃখিত, তবে আমি একজন শিক্ষানবিস আমার শুরু করার জন্য কিছু দরকার, তাই না? আপনি কি
এটির

উত্তর:


13

অ-পাঠ্য রূপকে ফিল্টার করার জন্য রূপচিকিত্সা ব্যবহার করে এখানে একটি সম্ভাব্য পন্থা । ধারণাটি হ'ল:

  1. বাইনারি ইমেজ প্রাপ্ত। চিত্র, গ্রেস্কেল লোড করুন, তারপরে ওসুর প্রান্তরে

  2. অনুভূমিক এবং উল্লম্ব লাইন সরান। এর cv2.getStructuringElementসাথে লাইনগুলি সরিয়ে ব্যবহার করে অনুভূমিক এবং উল্লম্ব কার্নেল তৈরি করুনcv2.drawContours

  3. তির্যক রেখা, চেনাশোনা বস্তু এবং বক্ররেখার সরান। পাঠ্যবিহীন রূপগুলি বিচ্ছিন্ন করতে কনট্যুর অঞ্চল cv2.contourArea এবং কনট্যুরের প্রায়শ ব্যবহার করে ফিল্টার করুনcv2.approxPolyDP

  4. পাঠ্য আরওআই এবং ওসিআর বের করুন। পিআইটিসেক্ট ব্যবহার করে ওসিআর এর পরে কনট্যুরগুলি এবং ফিল্টার সন্ধান করুন


সবুজতে হাইলাইট করা অনুভূমিক লাইনগুলি সরানো হয়েছে

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

উল্লম্ব লাইন সরানো হয়েছে

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

সরানো নন-পাঠ্য রূপগুলি (তির্যক রেখা, বৃত্তাকার বস্তু এবং বক্ররেখা) সরানো হয়েছে

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

পাঠ্য অঞ্চলগুলি সনাক্ত করা হয়েছে

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

import cv2
import numpy as np
import pytesseract

pytesseract.pytesseract.tesseract_cmd = r"C:\Program Files\Tesseract-OCR\tesseract.exe"

# Load image, grayscale, Otsu's threshold
image = cv2.imread('1.jpg')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]
clean = thresh.copy()

# Remove horizontal lines
horizontal_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (15,1))
detect_horizontal = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, horizontal_kernel, iterations=2)
cnts = cv2.findContours(detect_horizontal, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
    cv2.drawContours(clean, [c], -1, 0, 3)

# Remove vertical lines
vertical_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (1,30))
detect_vertical = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, vertical_kernel, iterations=2)
cnts = cv2.findContours(detect_vertical, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
    cv2.drawContours(clean, [c], -1, 0, 3)

cnts = cv2.findContours(clean, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
    # Remove diagonal lines
    area = cv2.contourArea(c)
    if area < 100:
        cv2.drawContours(clean, [c], -1, 0, 3)
    # Remove circle objects
    elif area > 1000:
        cv2.drawContours(clean, [c], -1, 0, -1)
    # Remove curve stuff
    peri = cv2.arcLength(c, True)
    approx = cv2.approxPolyDP(c, 0.02 * peri, True)
    x,y,w,h = cv2.boundingRect(c)
    if len(approx) == 4:
        cv2.rectangle(clean, (x, y), (x + w, y + h), 0, -1)

open_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (2,2))
opening = cv2.morphologyEx(clean, cv2.MORPH_OPEN, open_kernel, iterations=2)
close_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3,2))
close = cv2.morphologyEx(opening, cv2.MORPH_CLOSE, close_kernel, iterations=4)
cnts = cv2.findContours(close, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
    x,y,w,h = cv2.boundingRect(c)
    area = cv2.contourArea(c)
    if area > 500:
        ROI = image[y:y+h, x:x+w]
        ROI = cv2.GaussianBlur(ROI, (3,3), 0)
        data = pytesseract.image_to_string(ROI, lang='eng',config='--psm 6')
        if data.isalnum():
            cv2.rectangle(image, (x, y), (x + w, y + h), (36,255,12), 2)
            print(data)

cv2.imwrite('image.png', image)
cv2.imwrite('clean.png', clean)
cv2.imwrite('close.png', close)
cv2.imwrite('opening.png', opening)
cv2.waitKey()

প্রথমে সেই লাইনগুলি সরিয়ে ফেলার জন্য ভাল ধারণা।
করালফিলিপ

চিঠির
অংশগুলিও

8

ঠিক আছে, এখানে আরও একটি সম্ভাব্য সমাধান রয়েছে। আমি জানি আপনি পাইথন নিয়ে কাজ করেন - আমি সি ++ নিয়ে কাজ করি। আমি আপনাকে কিছু ধারণা দেব এবং আশা করি, আপনি যদি এটি চান তবে আপনি এই উত্তরটি প্রয়োগ করতে সক্ষম হবেন।

মূল ধারণাটি হ'ল প্রাক-প্রসেসিংটি মোটেও ব্যবহার না করা (কমপক্ষে প্রাথমিক পর্যায়ে নয়) এবং পরিবর্তে প্রতিটি লক্ষ্য অক্ষরে মনোনিবেশ করা, কিছু বৈশিষ্ট্য পাওয়া এবং প্রতিটি বৈশিষ্ট্যগুলি এই বৈশিষ্ট্য অনুসারে ফিল্টার করা।

আমি প্রাক-প্রক্রিয়াজাতকরণটি ব্যবহার না করার চেষ্টা করছি কারণ: 1) ফিল্টার এবং রূপচর্চা স্তরগুলি ব্লবের মানকে হ্রাস করতে পারে এবং 2) আপনার টার্গেট ব্লবগুলি এমন কিছু বৈশিষ্ট্য প্রদর্শন করে যা আমরা ব্যবহার করতে পারি, মূলত: দিক অনুপাত এবং ক্ষেত্র

এটি পরীক্ষা করে দেখুন, সংখ্যা এবং বর্ণগুলি সমস্ত বৃহত্তর থেকে লম্বা বলে মনে হচ্ছে ... তদুপরি, এগুলি নির্দিষ্ট ক্ষেত্রের মানের মধ্যে পৃথক হয়ে দেখা দেয়। উদাহরণস্বরূপ, আপনি "খুব প্রশস্ত" বা "খুব বড়" অবজেক্টগুলি বাতিল করতে চান ।

ধারণাটি হ'ল আমি প্রাক-গণনা করা মানগুলির মধ্যে না পড়ে এমন সব ফিল্টার করব। আমি অক্ষরগুলি (সংখ্যা এবং অক্ষর) পরীক্ষা করেছি এবং সর্বনিম্ন, সর্বাধিক ক্ষেত্রের মান এবং একটি ন্যূনতম দিক অনুপাত (এখানে, উচ্চতা এবং প্রস্থের মধ্যে অনুপাত) নিয়ে এসেছি।

আসুন আলগোরিদিম নিয়ে কাজ করি। চিত্রটি পড়ে এবং এটিটিকে আধটি মাত্রায় পুনরায় আকার দিয়ে শুরু করুন। আপনার চিত্রটি বেশ বড়। গ্রেস্কেলতে রূপান্তর করুন এবং otsu এর মাধ্যমে একটি বাইনারি চিত্র পান, এখানে সিউডো কোড রয়েছে:

//Read input:
inputImage = imread( "diagram.png" );

//Resize Image;
resizeScale = 0.5;

inputResized = imresize( inputImage, resizeScale );

//Convert to grayscale;
inputGray = rgb2gray( inputResized );

//Get binary image via otsu:
binaryImage = imbinarize( inputGray, "Otsu" );

কুল। আমরা এই চিত্রটি নিয়ে কাজ করব। আপনার প্রতিটি সাদা ব্লব পরীক্ষা করতে হবে এবং একটি "বৈশিষ্ট্য ফিল্টার" প্রয়োগ করতে হবে । আমি প্রতিটি ব্লবকে লুপ ট্রুপের জন্য পরিসংখ্যানগুলির সাথে সংযুক্ত উপাদানগুলি ব্যবহার করছি এবং এর ক্ষেত্র এবং দিক অনুপাত পেয়েছি , সি ++ এ এটি নিম্নলিখিতভাবে করা হয়েছে:

//Prepare the output matrices:
cv::Mat outputLabels, stats, centroids;
int connectivity = 8;

//Run the binary image through connected components:
int numberofComponents = cv::connectedComponentsWithStats( binaryImage, outputLabels, stats, centroids, connectivity );

//Prepare a vector of colors  color the filtered blobs in black
std::vector<cv::Vec3b> colors(numberofComponents+1);
colors[0] = cv::Vec3b( 0, 0, 0 ); // Element 0 is the background, which remains black.

//loop through the detected blobs:
for( int i = 1; i <= numberofComponents; i++ ) {

    //get area:
    auto blobArea = stats.at<int>(i, cv::CC_STAT_AREA);

    //get height, width and compute aspect ratio:
    auto blobWidth = stats.at<int>(i, cv::CC_STAT_WIDTH);
    auto blobHeight = stats.at<int>(i, cv::CC_STAT_HEIGHT);
    float blobAspectRatio = (float)blobHeight/(float)blobWidth;

    //Filter your blobs

};

এখন, আমরা বৈশিষ্ট্য ফিল্টার প্রয়োগ করব। এটি প্রাক-গণনাযুক্ত প্রান্তিকের সাথে কেবল একটি তুলনা। আমি নিম্নলিখিত মানগুলি ব্যবহার করেছি:

Minimum Area: 40  Maximum Area:400
MinimumAspectRatio:  1

আপনার forলুপের অভ্যন্তরে , বর্তমান অঙ্কুরের বৈশিষ্ট্যগুলি এই মানগুলির সাথে তুলনা করুন। যদি পরীক্ষাগুলি ইতিবাচক হয় তবে আপনি ব্লব কালোটি "আঁকুন"। forলুপের ভিতরে অবিরত :

    //Filter your blobs

    //Test the current properties against the thresholds:
    bool areaTest =  (blobArea > maxArea)||(blobArea < minArea);
    bool aspectRatioTest = !(blobAspectRatio > minAspectRatio); //notice we are looking for TALL elements!

    //Paint the blob black:
    if( areaTest || aspectRatioTest ){
        //filtered blobs are colored in black:
        colors[i] = cv::Vec3b( 0, 0, 0 );
    }else{
        //unfiltered blobs are colored in white:
        colors[i] = cv::Vec3b( 255, 255, 255 );
    }

লুপের পরে, ফিল্টারকৃত চিত্রটি তৈরি করুন:

cv::Mat filteredMat = cv::Mat::zeros( binaryImage.size(), CV_8UC3 );
for( int y = 0; y < filteredMat.rows; y++ ){
    for( int x = 0; x < filteredMat.cols; x++ )
    {
        int label = outputLabels.at<int>(y, x);
        filteredMat.at<cv::Vec3b>(y, x) = colors[label];
    }
}

এবং thats প্রায় কাছাকাছি এটি. আপনি যে সমস্ত উপাদান সন্ধান করছেন তার মতো নয় এমন সমস্ত উপাদান আপনি ফিল্টার করেছেন। অ্যালগরিদম চালানো আপনি এই ফলাফলটি পান:

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

ফলাফলগুলি আরও ভালভাবে কল্পনা করতে আমি অতিরিক্তভাবে ব্লবগুলির বাউন্ডিং বক্সগুলি পেয়েছি:

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

আপনি যেমন দেখতে পাচ্ছেন কিছু উপাদান মিস-শনাক্ত করা হয়েছে। আপনি যে অক্ষরগুলি সন্ধান করছেন সেগুলি আরও ভাল করে সনাক্ত করতে আপনি "বৈশিষ্ট্য ফিল্টার" পরিমার্জন করতে পারেন। একটি গভীর সমাধান, সামান্য কিছুটা মেশিন লার্নিংয়ের সাথে জড়িত, একটি "আদর্শ বৈশিষ্ট্য ভেক্টর" তৈরি করা, ব্লবগুলি থেকে বৈশিষ্ট্যগুলি নিষ্কাশন করা, এবং উভয় ভেক্টরকে একটি সাদৃশ্য পরিমাপের সাথে তুলনা করার প্রয়োজন। আপনি ফলাফল উন্নত করতে কিছু পোস্ট- প্রসেসিং প্রয়োগ করতে পারেন ...

যাই হউক, মানুষ, আপনার সমস্যাটি তুচ্ছ বা সহজ পরিমাণে স্কেলযোগ্য নয় এবং আমি আপনাকে কেবল ধারণা দিচ্ছি। আশা করি, আপনি নিজের সমাধানটি কার্যকর করতে সক্ষম হবেন।


যে কোনও সুযোগ আপনি একই প্রোগ্রামটিকে
অজগরে

@ পুলকিতভাটনগর হ্যাঁ, অবশ্যই। আপনি কেবল শক্ত করে ধরে রাখুন, আমার কয়েক মিনিটের মধ্যে একটি নিখুঁত বন্দর প্রস্তুত থাকবে।
ওয়ান্ডগ্র্যাসিয়াদো

?? আপনি কি তা করেছিলেন, যাতে আমি আপনাকে
অনুদানের

অই হ্যাঁ. আমি ভীষণ দুঃখিত, আমার স্যার, আমি কিছুটা সমস্যায় পড়েছিলাম, তবে রূপান্তরটি খুব সুন্দরভাবেই আসছিল। শুধু তুমি অপেক্ষা করো. ধন্যবাদ.
শে

কখনই ভাবিনি যে এটি কটূক্তি হতে পারে।
পুলকিত ভাটনগর

4

একটি পদ্ধতি হ'ল স্লাইডিং উইন্ডোটি ব্যবহার করা (এটি ব্যয়বহুল)।

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


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