Được rồi, đây là một giải pháp khả thi khác. Tôi biết bạn làm việc với Python - Tôi làm việc với C ++. Tôi sẽ cung cấp cho bạn một số ý tưởng và hy vọng, nếu bạn mong muốn như vậy, bạn sẽ có thể thực hiện câu trả lời này.
Ý tưởng chính là hoàn toàn không sử dụng tiền xử lý (ít nhất là không ở giai đoạn ban đầu) và thay vào đó tập trung vào từng nhân vật mục tiêu, nhận một số thuộc tính và lọc mọi blob theo các thuộc tính này.
Tôi đang cố gắng không sử dụng tiền xử lý vì: 1) Các bộ lọc và giai đoạn hình thái có thể làm giảm chất lượng của các đốm màu và 2) các đốm màu mục tiêu của bạn dường như thể hiện một số đặc điểm mà chúng ta có thể khai thác, chủ yếu là: tỷ lệ khung hình và diện tích .
Hãy kiểm tra xem, tất cả các số và chữ có vẻ cao hơn rộng hơn nữa, chúng dường như thay đổi trong một giá trị khu vực nhất định. Ví dụ: bạn muốn loại bỏ các đối tượng "quá rộng" hoặc "quá lớn" .
Ý tưởng là tôi sẽ lọc mọi thứ không nằm trong các giá trị được tính toán trước. Tôi đã kiểm tra các ký tự (số và chữ) và đi kèm với các giá trị diện tích tối thiểu, tối đa và tỷ lệ khung hình tối thiểu (ở đây, tỷ lệ giữa chiều cao và chiều rộng).
Hãy làm việc với thuật toán. Bắt đầu bằng cách đọc hình ảnh và thay đổi kích thước của nó thành một nửa kích thước. Hình ảnh của bạn quá lớn Chuyển đổi sang thang độ xám và nhận hình ảnh nhị phân qua otsu, đây là mã giả:
//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" );
Mát mẻ. Chúng tôi sẽ làm việc với hình ảnh này. Bạn cần kiểm tra từng đốm trắng và áp dụng "bộ lọc thuộc tính" . Tôi đang sử dụng các thành phần được kết nối với các số liệu thống kê để lặp lại từng máng và lấy tỷ lệ diện tích và khía cạnh của nó, trong C ++, việc này được thực hiện như sau:
//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…
};
Bây giờ, chúng tôi sẽ áp dụng bộ lọc thuộc tính. Đây chỉ là một so sánh với các ngưỡng được tính toán trước. Tôi đã sử dụng các giá trị sau:
Minimum Area: 40 Maximum Area:400
MinimumAspectRatio: 1
Trong for
vòng lặp của bạn , so sánh các thuộc tính blob hiện tại với các giá trị này. Nếu các xét nghiệm dương tính, bạn "vẽ" màu đen của blob. Tiếp tục bên trong for
vòng lặp:
//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 );
}
Sau vòng lặp, xây dựng hình ảnh được lọc:
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];
}
}
Và đó là khá nhiều đó. Bạn đã lọc tất cả các yếu tố không giống với những gì bạn đang tìm kiếm. Chạy thuật toán bạn nhận được kết quả này:
Ngoài ra, tôi còn tìm thấy Hộp Bounding của các đốm màu để hình dung rõ hơn về kết quả:
Như bạn thấy, một số yếu tố bị phát hiện sai. Bạn có thể tinh chỉnh "bộ lọc thuộc tính" để xác định tốt hơn các ký tự bạn đang tìm kiếm. Một giải pháp sâu hơn, liên quan đến một chút học máy, đòi hỏi phải xây dựng một "vectơ đặc trưng lý tưởng", trích xuất các tính năng từ các đốm màu và so sánh cả hai vectơ thông qua một phép đo tương tự. Bạn cũng có thể áp dụng một số xử lý hậu kỳ để cải thiện kết quả ...
Dù sao đi nữa, vấn đề của bạn không phải là tầm thường hay dễ mở rộng, và tôi chỉ đưa ra ý tưởng cho bạn. Hy vọng, bạn sẽ có thể thực hiện giải pháp của bạn.