เอาล่ะนี่เป็นอีกวิธีที่เป็นไปได้ ฉันรู้ว่าคุณทำงานกับ Python - ฉันทำงานกับ C ++ ฉันจะให้ความคิดและหวังว่าหากคุณต้องการคุณจะสามารถใช้คำตอบนี้ได้
แนวคิดหลักคือไม่ใช้การประมวลผลล่วงหน้าเลย (อย่างน้อยไม่ได้อยู่ในขั้นเริ่มต้น) และแทนที่จะมุ่งเน้นไปที่ตัวละครเป้าหมายแต่ละตัวรับคุณสมบัติบางอย่างและกรองทุกหยดตามคุณสมบัติเหล่านี้
ฉันพยายามที่จะไม่ใช้การประมวลผลก่อนเนื่องจาก 1) การกรองและขั้นตอนก้านอาจลดคุณภาพของ blobs และ 2) blobs เป้าหมายของคุณดูเหมือนจะแสดงลักษณะบางอย่างที่เราสามารถใช้ประโยชน์จากส่วนใหญ่: อัตราส่วนและพื้นที่
ลองดูสิตัวเลขและตัวอักษรทั้งหมดดูเหมือนจะสูงกว่ากว้างกว่า ... นอกจากนี้พวกมันดูเหมือนจะแปรผันไปตามค่าของพื้นที่ ตัวอย่างเช่นคุณต้องการที่จะทิ้งวัตถุ"กว้างเกินไป"หรือ"ใหญ่เกินไป"
แนวคิดคือฉันจะกรองทุกอย่างที่ไม่ได้อยู่ในค่าที่คำนวณไว้ล่วงหน้า ฉันตรวจสอบอักขระ (ตัวเลขและตัวอักษร) และมาพร้อมกับค่าพื้นที่ต่ำสุดค่าสูงสุดและอัตราส่วนต่ำสุด (ที่นี่คืออัตราส่วนระหว่างความสูงและความกว้าง)
มาทำงานกับอัลกอริทึมกัน เริ่มต้นด้วยการอ่านภาพและปรับขนาดให้เล็กลงครึ่งหนึ่ง ภาพของคุณใหญ่เกินไป แปลงเป็นระดับสีเทาและรับภาพไบนารีผ่าน 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" );
เย็น. เราจะทำงานกับภาพนี้ คุณจำเป็นต้องตรวจสอบทุกหยดสีขาวและใช้"คุณสมบัติกรอง" ฉันใช้ส่วนประกอบที่เชื่อมต่อกับสถิติเพื่อลูปรางแต่ละหยดและรับพื้นที่และอัตราส่วนกว้างยาวของมันใน C ++ สามารถทำได้ดังนี้:
//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];
}
}
และ…มันก็สวยมาก คุณกรององค์ประกอบทั้งหมดที่ไม่คล้ายกับสิ่งที่คุณกำลังมองหา ใช้อัลกอริทึมที่คุณได้รับผลลัพธ์นี้:
ฉันได้ค้นพบกล่อง Bounding Boxes ของ blobs เพิ่มเติมเพื่อให้เห็นภาพผลลัพธ์ที่ดีขึ้น:
อย่างที่คุณเห็นองค์ประกอบบางอย่างถูกตรวจพบพลาด คุณสามารถปรับแต่ง "ตัวกรองคุณสมบัติ" เพื่อระบุตัวละครที่คุณกำลังมองหาได้ดียิ่งขึ้น โซลูชันที่ลึกกว่าซึ่งเกี่ยวข้องกับการเรียนรู้ของเครื่องจักรเพียงเล็กน้อยจำเป็นต้องมีการสร้าง "เวกเตอร์คุณลักษณะที่สมบูรณ์แบบ" การแยกคุณสมบัติจาก blobs และเปรียบเทียบเวกเตอร์ทั้งสองผ่านการวัดความคล้ายคลึงกัน นอกจากนี้คุณยังสามารถใช้การประมวลผลภายหลังเพื่อปรับปรุงผลลัพธ์ ...
ไม่ว่าอะไรก็ตามปัญหาของคุณไม่ใช่เรื่องง่ายและปรับขนาดได้ง่ายและฉันแค่ให้ความคิดกับคุณ หวังว่าคุณจะสามารถใช้โซลูชันของคุณได้