1. 程式人生 > >opencv字元分割

opencv字元分割

投影法

#include<iostream>
#include <opencv2/opencv.hpp>
#include <stdio.h>

using namespace std;
using namespace cv;



//************************************************************************************



Mat vertical_projection(Mat & input_src, Mat src) //輸入二值化圖片
{
	/**************統計原圖片中每列白色畫素數目******************************/
	int src_width = input_src.cols;
	int src_height = input_src.rows;
	int* col_array = new int[src_width]();//建立用於儲存每列白色畫素個數的陣列
	//memset(col_array, 0, src_width*4);//初始化陣列
	//取列白色畫素個數
	for (int i = 0; i < src_height; i++){
		for (int j = 0; j < src_width; j++){
			if (input_src.at<uchar>(i, j)){
				col_array[j]++;
			}
		}
	}
	/**************將每列白色畫素數目繪製成直方圖***************************/
	//定義畫布 繪製垂直投影下每列白色畫素的數目
	Mat draw_col(src_height, src_width, CV_8UC1, Scalar(0));
	for (int i = 0; i< src_width; i++){
		for (int j = 0; j < col_array[i]; j++){
			draw_col.at<uchar>(src_height-j-1,i) = 255;
		}
	}
	imshow("draw_col", draw_col);

	/**************統計原圖片中每行白色畫素數目******************************/
	int* row_array = new int[src_height]();//建立用於儲存每行白色畫素個數的陣列
	//memset(row_array, 0, src_width*4);//初始化陣列
	//取列白色畫素個數
	for (int i = 0; i < src_height; i++){
		for (int j = 0; j < src_width; j++){
			if (input_src.at<uchar>(i, j)){
				row_array[i]++;
			}
		}
	}
	/**************將每行白色畫素數目繪製成直方圖***************************/
	//定義畫布 繪製垂直投影下每行白色畫素的數目
	Mat draw_row(src_height, src_width, CV_8UC1, Scalar(0));
	for (int i = 0; i< src_height; i++){
		for (int j = 0; j < row_array[i]; j++){
			draw_row.at<uchar>(i,src_width-j-1) = 255;
		}
	}
	imshow("draw_row", draw_row);


	/*********根據每列白色畫素數目設定擷取起始和截止列***********************/
	//定義Mat vector ,儲存圖片組
	vector<Mat> split_src;
	//定義標誌,用來指示在白色畫素區還是在全黑區域
	bool white_block_col = 0, black_block_col = 0;
	//定義列temp_col_forword  temp_col_behind,記錄字元擷取起始列和截止列
	int temp_col_forword=0,temp_col_behind = 0;
	Mat split_temp;
	vector<int> col_begin;
	vector<int> col_end;
	//遍歷陣列col_array
	for (int i = 0; i < src_width; i++){
		if (col_array[i]){//表示區域有白色畫素
			white_block_col = 1;
			black_block_col = 0;
		}
		else{				//若無白色畫素(進入黑色區域)
			if (white_block_col == 1){//若前一列有白色畫素
				temp_col_behind = i;//取當前列為截止列
				////擷取下一部分
				//input_src(Rect(temp_col_forword, 0, temp_col_behind - temp_col_forword, src_height)).copyTo(split_temp);
				//split_src.push_back(split_temp);
				col_begin.push_back(temp_col_forword);
				col_end.push_back(temp_col_behind);
			}
			temp_col_forword = i;//記錄最新黑色區域的列號,記為起始列
			black_block_col = 1;//表示進入黑色區域
			white_block_col = 0;
		}
	}

	//遍歷陣列row_array
	vector<int> row_begin;
	vector<int> row_end;

	bool white_block_row = 0, black_block_row = 0;
	int temp_row_forword=0, temp_row_behind = 0;
	for (int i = 0; i < src_height; i++){
		if (row_array[i]){//表示區域有白色畫素
			white_block_row = 1;
			black_block_row = 0;
		}
		else{				//若無白色畫素(進入黑色區域)
			if (white_block_row == 1){//若前一列有白色畫素
				temp_row_behind = i;//取當前列為截止列
				////擷取下一部分
				//input_src(Rect(temp_col_forword, 0, temp_col_behind - temp_col_forword, src_height)).copyTo(split_temp);
				//split_src.push_back(split_temp);
				row_begin.push_back(temp_row_forword);
				row_end.push_back(temp_row_behind);
			}
			temp_row_forword = i;//記錄最新黑色區域的列號,記為起始列
			black_block_row = 1;//表示進入黑色區域
			white_block_row = 0;
		}
	}

	vector<Mat> segmentation;

		for (unsigned int j = 0; j < col_end.size(); j++)
		{
			Mat temp = src(Range(row_begin[0] + 800,row_end[0] + 800), 
								Range(col_begin[j] + 650, col_end[j] + 650));
			segmentation.push_back(temp);
		}
		for (unsigned int j = 3; j < col_end.size() - 2; j++)
		{
			Mat temp = src(Range(row_begin[1] + 800,row_end[1] + 800), 
				Range(col_begin[j] + 650, col_end[j] + 650));
			segmentation.push_back(temp);
		}
	

	for (unsigned int i = 0 ; i < segmentation.size(); i++)
	{
		string s = to_string(i + 1);
		//imshow(s, segmentation[i]);
		string filename = "F:\\分割圖片\\4\\" + s + ".bmp";
		imwrite(filename, segmentation[i]);
	}
	waitKey(0);
	return input_src;
}



int main()
{
	Mat src = imread("F:\\PIN_LENGTH\\4.bmp");
	Mat roi = src(Range(800,1200), Range(650,1600));
	Mat roi_gray;
	cvtColor(roi, roi_gray, CV_BGR2GRAY, 1);		//轉換為單通道
	Mat roi_gray_blur;
	blur(roi_gray, roi_gray_blur, Size(3,3));		//濾波
	Mat roi_gray_blur_thresh;
	threshold(roi_gray_blur, roi_gray_blur_thresh, 200, 255, THRESH_BINARY_INV);	//二值化
	imshow("canny", roi_gray_blur_thresh);

	vertical_projection(roi_gray_blur_thresh , src);


	/*imshow("sdf", roi);
	namedWindow("src", WINDOW_NORMAL);
	imshow("src", src);*/
	waitKey(0);
}