1 | initial version |
I would use binary threshold, morphology and contours to solve this problem.
Step 1 : get the copy with signature
cv::Mat const map_01 = cv::imread("map01.jpg");
Step 2 : blur the image and convert it to binary image
cv::Mat binarize;
cv::cvtColor(map_01, binarize, CV_BGR2GRAY);
cv::GaussianBlur(map_01, map_01, {5,5}, 3,3);
cv::threshold(binarize, binarize, 0, 255,
cv::THRESH_BINARY_INV | cv::THRESH_OTSU);
Step 3 : Use morphology to remove small blobs and make text blobs more obvious
auto mrect = cv::getStructuringElement(cv::MORPH_RECT, {3,3});
cv::erode(binarize, binarize, mrect);
mrect = cv::getStructuringElement(cv::MORPH_RECT, {7,5});
cv::morphologyEx(binarize, binarize, cv::MORPH_DILATE, mrect, {-1,-1}, 7);
Step 4 : find contours and remove those with invalid aspect ratio
std::vector<std::vector<cv::Point>> contours;
cv::findContours(binarize.clone(), contours, CV_RETR_EXTERNAL,
CV_CHAIN_APPROX_SIMPLE);
auto rit = std::remove_if(std::begin(contours), std::end(contours),
[](auto const &ct)
{
auto const rect = cv::boundingRect(ct);
return rect.height > rect.width;
});
contours.erase(rit, std::end(contours));
Step 5 : Find the data of each rectangle
for(auto const &ct : contours){
//get the information of each rect
cv::Mat temp = map_01.clone();
std::cout<<cv::boundingRect(ct)<<std::endl;
cv::rectangle(temp, cv::boundingRect(ct), {255,0,0});
cv::imshow("temp", temp);
cv::waitKey();
cv::destroyAllWindows();
}
The bounding rects found by this solution are
Step 6 : Extract text location according to the location and size of the bounding rects, this step is quite tedious.
Not a very good one, I believe there exist better solution, like find the difference between two images.
Source codes locate at github.
2 | No.2 Revision |
I would use binary threshold, morphology and contours to solve this problem.
Step 1 : get the copy with signature
cv::Mat const map_01 = cv::imread("map01.jpg");
Step 2 : blur the image and convert it to binary image
cv::Mat binarize;
cv::cvtColor(map_01, binarize, CV_BGR2GRAY);
cv::GaussianBlur(map_01, map_01, {5,5}, 3,3);
cv::threshold(binarize, binarize, 0, 255,
cv::THRESH_BINARY_INV | cv::THRESH_OTSU);
Step 3 : Use morphology to remove small blobs and make text blobs more obvious
auto mrect = cv::getStructuringElement(cv::MORPH_RECT, {3,3});
cv::erode(binarize, binarize, mrect);
mrect = cv::getStructuringElement(cv::MORPH_RECT, {7,5});
cv::morphologyEx(binarize, binarize, cv::MORPH_DILATE, mrect, {-1,-1}, 7);
Step 4 : find contours and remove those with invalid aspect ratio
std::vector<std::vector<cv::Point>> contours;
cv::findContours(binarize.clone(), contours, CV_RETR_EXTERNAL,
CV_CHAIN_APPROX_SIMPLE);
auto rit = std::remove_if(std::begin(contours), std::end(contours),
[](auto const &ct)
{
auto const rect = cv::boundingRect(ct);
return rect.height > rect.width;
});
contours.erase(rit, std::end(contours));
Step 5 : Find the data of each rectangle
for(auto const &ct : contours){
//get the information of each rect
cv::Mat temp = map_01.clone();
std::cout<<cv::boundingRect(ct)<<std::endl;
cv::rectangle(temp, cv::boundingRect(ct), {255,0,0});
cv::imshow("temp", temp);
cv::waitKey();
cv::destroyAllWindows();
}
The bounding rects found by this solution are
Step 6 : Extract text location according to the location and size of the bounding rects, this step is quite tedious.
Not a very good one, I believe there exist better solution, like find the difference between two images.
Source codes locate at github.
Edit : If the format and size of the are always the same, you can predefined the bounding rect of text candidates, extract the roi from predefined bounding rect, detect the binary value of those roi to find out the regions filled or not.