文字分隔方法很多。最合適是聚類方法,本例在輪廓基礎提取文字區域,速度在PC上最快。用Canny算子+findcontour函數可以提取目標的輪廓。輪廓提取後矩形框包圍文字部分。最後對矩形進行篩選。
假設,對於下面二值化圖像。
過濾後的輪廓所在的矩形框基本能滿足需求,直接上源碼:
#include <opencv2//opencv.hpp>
#include <iostream>
#include <string>
using namespace cv;
using namespace std;
#define g_threshold 200;
int main(int argc, char* argv[])
{
string input;
Mat imageSource = imread("G:\\1.bmp", 0);
imshow("原始圖像", imageSource);
Mat image;
int p_threshold;
//std::pair<float, float> pair1 = cal_mean_std(imageSource.data,imageSource.rows, imageSource.cols);
//p_threshold = (int)pair1.first;
threshold(imageSource, image, 80,255,0);
medianBlur(image, image, 7);
imshow("二值化圖像", image);
int area=0;
for (int i = 0; i < imageSource.rows; i++)
{
for (int j = 0; j < imageSource.cols; j++)
{
if (image.at<uchar>(i, j) = 255) { area++; }
}
}
if(area> imageSource.cols*imageSource.rows/2)
{ bitwise_not(image, image);
}
//image.copyTo(imageSource);
blur(imageSource, imageSource, cv::Size(3,3));
Canny(imageSource, image, 80, 250,3);
imshow("canny圖像", image);
vector<vector<Point>> contours;
vector<Vec4i> hierarchy;
findContours(image, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_NONE, Point());
Mat imageContours = Mat::zeros(image.size(), CV_8UC1);
Mat Contours = Mat::zeros(image.size(), CV_8UC1); //繪製
Mat src = Mat::zeros(image.size(), CV_8UC3);
//src.data[0] = image.data;
int num = contours.size();
vector<cv::Rect> boundRect(num);
num = 0;
for (int i = 0; i < contours.size(); i++)
{
//contours[i]代表的是第i個輪廓,contours[i].size()代表的是第i個輪廓上所有的像素點數
for (int j = 0; j < contours[i].size(); j++)
{
//繪製出contours向量所有的像素點
Point P = Point(contours[i][j].x, contours[i][j].y);
Contours.at<uchar>(P) = 255;
}
//輸出hierarchy向量內容
char ch[256];
sprintf(ch, "%d", i);
string str = ch;
//cout << "向量hierarchy的第" << str << "個元素內容爲:" << hierarchy[i] << endl << endl;
//繪製輪廓
int area = contourArea(contours[i], true);
if (contourArea(contours[i], true) > 150 && contourArea(contours[i]) < 8000, true)
{
drawContours(imageContours, contours,
i, Scalar(255), CV_FILLED, 8, hierarchy);
Mat roi,roi2;
cv::Rect rect = cv::boundingRect((cv::Mat)contours[i]);
roi = image(rect);
roi2 = imageContours(rect);
boundRect[i].x = rect.x;
boundRect[i].y = rect.y;
boundRect[i].width = rect.width;
boundRect[i].height = rect.height;
if (rect.width > 20&& rect.height<200) {
printf("%d,%d,%d,%d\t", rect.x, rect.y, rect.width, rect.height);
num++;
Mat roi3;
roi.copyTo(roi3, roi2);
ostringstream of;
of << "G:\\SVM-OCR\\Template\\" << i+222 << ".jpg";
cv::resize(roi3, roi3, cv::Size(32, 32));
cv::imwrite(of.str(), roi3);
cv::rectangle(src, cv::Point(rect.x, rect.y), cv::Point(rect.width + rect.x, rect.height + rect.y), cv::Scalar(255), 3);
}
}
}
//cv::(src,src, imageContours);
imshow("Contours Image rectang", src); //輪廓
imshow("Point of Contours CV_CHAIN_APPROX_NONE", Contours); //向量contours內保存的所有輪廓點集
waitKey(80000);
//Mat roi = image(Contours[i]);
return 0;
}
轉載請註明:轉載於CSDN windly_al
圖像分割的效果如下: