对文本中的多行进行分割
直接上代码
#include<opencv2/imgproc/imgproc.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/core/core.hpp>
#include<iostream>
#include <stdio.h>
using namespace std;
using namespace cv;
Mat vertical_projection(Mat input_src) //基于Y轴垂直投影分割算法(输入的是二值图像)
{
/**************统计原图片中每行黑色像素数目******************************/
blur(input_src, input_src, Size(3, 3));//对输入的二值图像进行3*3均值滤波(blur是均值滤波函数)
int src_width = input_src.cols; //获得二值图像的列数(宽)(列的像素点个数)
int src_height = input_src.rows; //获得二值图像的行数(高)(行的像素点个数)
int* projectValArry = new int[src_height]();//创建用于储存每行黑色像素个数的数组
//在行的基础下遍历每一列,取列黑色像素个数,获得储存每行黑色像素个数的数组
for (int i = 0; i < src_height; i++){
for (int j = 0; j < src_width; j++){
if (input_src.at<uchar>(i, j) == 0) //at:取出二值图像的i行j列的像素点,如果他是黑色,则存取
{
projectValArry[i]++; //每一行的黑色像素个数加一
}
}
}
for (int i = 0; i < src_height; i++) //验证下每行存的值(应该是有0的)
{
cout << projectValArry[i] << endl;
}
/**************将每行黑色像素数目绘制成直方图***************************/
//定义画布 绘制Y轴垂直投影下每行黑色像素的数目
Mat verticalProjectionMat(src_height, src_width, CV_8UC1, Scalar(255)); //定义一个和原图像大小相同的全1(白色)的画布图像
for (int i = 0; i< src_height; i++){
for (int j = 0; j < projectValArry[i]; j++){
verticalProjectionMat.at<uchar>(i, j) = 0; //在图像左侧绘制直方图
}
}
imshow("verticalProjectionMat", verticalProjectionMat); //显示直方图(往Y-轴投影的直方图)
imwrite("image_histogram.png", verticalProjectionMat);
/*********根据每列白色像素数目设置截取起始和截止列***********************/
//定义Mat vector ,存储图片数组
vector<Mat> split_src;
//定义标志,用来指示在白色像素区还是在全黑区域
bool white_block = 0, black_block = 0;
//定义列temp_col_forword temp_col_behind,记录字符截取起始行和截止行
int temp_row_forword = 0, temp_row_behind = 0;
Mat split_temp;
//遍历数组projectValArry
for (int i = 0; i < src_height; i++){
if (projectValArry[i]){//表示区域有黑色像素
white_block = 0;
black_block = 1;
}
else{ //若无黑色像素(进入白色区域)
if (black_block == 1){//若前一列有黑色像素
temp_row_behind = i;//取当前列为截止列
//截取下一部分
//clone:把input_src(Rect()),即矩形区域内的信息完全拷贝给split_temp,是Mat类型
split_temp = input_src(Rect(0, temp_row_forword-5, src_width, temp_row_behind - temp_row_forword+10)).clone();
split_src.push_back(split_temp); //将此区域Mat存到Mat数组中
}
temp_row_forword = i;//记录最新白色区域的列号,记为起始列
black_block = 0;//表示进入白色区域
white_block = 1;
}
}
/*********显示分割后的每个图片***********************/
for (int i = 0; i < split_src.size(); i++){
char window[20];
sprintf(window, " split: %d", i);
imshow(window, split_src[i]); //显示分割后的图片
string imagename = "D:\\soft\\VS2013\\Project-test\\test_opencv\\test_opencv\\"+ to_string(i) + ".png";
imwrite(imagename.c_str(), split_src[i]); //保存图片
}
waitKey(0);
return input_src;
}
int main()
{
Mat srcImage = imread("C:\\Users\\12534\\Desktop\\2.png");
imshow("Original_image", srcImage);
if (!srcImage.data){
cout << "failed to read" << endl; //如果读取不了Mat中的数据,则打印读取失败
system("pause");
return -1;
}
Mat srcGray;
cvtColor(srcImage, srcGray, CV_BGR2GRAY); //将传入的BGR图片转换成灰度图片
Mat bin_src;
threshold(srcGray, bin_src, 100, 255, CV_THRESH_OTSU); //基于最大类间方差法(otsu)(获得最佳阈值)的图像二值化
imshow("bin_src", bin_src); //显示二值图像
imwrite("bin_src.png", bin_src);
vertical_projection(bin_src);
waitKey(0);
return 0;
}
- 原图像
- 二值图像(bin_src.png)
- 二值图像的直方图(image_histogram.png)
- 分割后的图片