對文本中的多行進行分割
直接上代碼
#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)
- 分割後的圖片