Baiklah, inilah solusi lain yang mungkin. Saya tahu Anda bekerja dengan Python - Saya bekerja dengan C ++. Saya akan memberi Anda beberapa ide dan mudah-mudahan, jika Anda menginginkannya, Anda akan dapat menerapkan jawaban ini.
Gagasan utamanya adalah untuk tidak menggunakan pra-pemrosesan sama sekali (setidaknya tidak pada tahap awal) dan sebaliknya fokus pada setiap karakter target, dapatkan beberapa properti , dan filter setiap gumpalan sesuai dengan properti ini.
Saya mencoba untuk tidak menggunakan pra-pemrosesan karena: 1) Filter dan tahapan morfologis dapat menurunkan kualitas gumpalan dan 2) gumpalan target Anda tampaknya menunjukkan beberapa karakteristik yang dapat kami eksploitasi, terutama: rasio aspek dan area .
Lihat saja, angka dan huruf semuanya tampak lebih tinggi daripada yang lebih luas ... lebih jauh lagi, semuanya tampak bervariasi dalam nilai area tertentu. Misalnya, Anda ingin membuang objek "terlalu lebar" atau "terlalu besar" .
Idenya adalah bahwa saya akan memfilter semua yang tidak termasuk dalam nilai yang telah dihitung sebelumnya. Saya memeriksa karakter (angka dan huruf) dan datang dengan nilai area minimum, maksimum dan rasio aspek minimum (di sini, rasio antara tinggi dan lebar).
Mari kita bekerja pada algoritma. Mulailah dengan membaca gambar dan mengubah ukurannya menjadi setengah dimensi. Gambar Anda terlalu besar. Konversikan ke skala abu-abu dan dapatkan gambar biner melalui otsu, berikut dalam pseudo-code:
//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" );
Keren. Kami akan bekerja dengan gambar ini. Anda perlu memeriksa setiap gumpalan putih, dan menerapkan "filter properti" . Saya menggunakan komponen yang terhubung dengan statistik untuk loop melalui setiap gumpalan dan mendapatkan area dan aspek rasio, di C ++ ini dilakukan sebagai berikut:
//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…
};
Sekarang, kita akan menerapkan filter properti. Ini hanya perbandingan dengan ambang yang dihitung sebelumnya. Saya menggunakan nilai-nilai berikut:
Minimum Area: 40 Maximum Area:400
MinimumAspectRatio: 1
Di dalam for
lingkaran Anda , bandingkan properti gumpalan saat ini dengan nilai-nilai ini. Jika hasil tes positif, Anda "mengecat" gumpalan hitam. Melanjutkan di dalam for
lingkaran:
//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 );
}
Setelah loop, buat gambar yang difilter:
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];
}
}
Dan ... cukup banyak. Anda memfilter semua elemen yang tidak mirip dengan yang Anda cari. Menjalankan algoritme Anda mendapatkan hasil ini:
Saya juga telah menemukan Bounding Boxes of the blob untuk lebih memvisualisasikan hasil:
Seperti yang Anda lihat, beberapa elemen tidak terdeteksi. Anda dapat memperbaiki "filter properti" untuk mengidentifikasi karakter yang Anda cari dengan lebih baik. Solusi yang lebih dalam, yang melibatkan sedikit pembelajaran mesin, membutuhkan konstruksi "vektor fitur ideal", mengekstraksi fitur dari gumpalan, dan membandingkan kedua vektor melalui ukuran kesamaan. Anda juga dapat menerapkan beberapa proses pasca untuk meningkatkan hasil ...
Apa pun, kawan, masalah Anda tidak sepele atau tidak mudah diukur, dan saya hanya memberi Anda ide. Semoga Anda dapat menerapkan solusi Anda.