opencv 垂直投影分割字符

来源:互联网 发布:网络打印机维修 编辑:程序博客网 时间:2024/06/01 10:57

原图:

#include "opencv2/imgproc/imgproc.hpp"#include "opencv2/highgui/highgui.hpp"#include <iostream>#include <stdio.h>using namespace cv;using namespace std;vector<Mat> horizontalProjectionMat(Mat srcImg)//水平投影{Mat binImg;blur(srcImg, binImg, Size(3, 3));threshold(binImg, binImg, 0, 255, CV_THRESH_OTSU);int perPixelValue = 0;//每个像素的值int width = srcImg.cols;int height = srcImg.rows;int* projectValArry = new int[height];//创建一个储存每行白色像素个数的数组memset(projectValArry, 0, height * 4);//初始化数组for (int col = 0; col < height; col++)//遍历每个像素点{for (int row = 0; row < width; row++){perPixelValue = binImg.at<uchar>(col, row);if (perPixelValue == 0)//如果是白底黑字{projectValArry[col]++;}}}Mat horizontalProjectionMat(height, width, CV_8UC1);//创建画布for (int i = 0; i < height; i++){for (int j = 0; j < width; j++){perPixelValue = 255;horizontalProjectionMat.at<uchar>(i, j) = perPixelValue;//设置背景为白色}}for (int i = 0; i < height; i++)//水平直方图{for (int j = 0; j < projectValArry[i]; j++){perPixelValue = 0;horizontalProjectionMat.at<uchar>(i, width - 1 - j) = perPixelValue;//设置直方图为黑色}}vector<Mat> roiList;//用于储存分割出来的每个字符int startIndex = 0;//记录进入字符区的索引int endIndex = 0;//记录进入空白区域的索引bool inBlock = false;//是否遍历到了字符区内for (int i = 0; i <srcImg.rows; i++){if (!inBlock && projectValArry[i] != 0)//进入字符区{inBlock = true;startIndex = i;}else if (inBlock && projectValArry[i] == 0)//进入空白区{endIndex = i;inBlock = false;Mat roiImg = srcImg(Range(startIndex, endIndex + 1), Range(0, srcImg.cols));//从原图中截取有图像的区域roiList.push_back(roiImg);}}delete[] projectValArry;return roiList;}vector<Mat> verticalProjectionMat(Mat srcImg)//垂直投影{Mat binImg;blur(srcImg, binImg, Size(3, 3));threshold(binImg, binImg, 0, 255, CV_THRESH_OTSU);int perPixelValue;//每个像素的值int width = srcImg.cols;int height = srcImg.rows;int* projectValArry = new int[width];//创建用于储存每列白色像素个数的数组memset(projectValArry, 0, width * 4);//初始化数组for (int col = 0; col < width; col++)//列{for (int row = 0; row < height; row++)//行{perPixelValue = binImg.at<uchar>(row, col);if (perPixelValue == 0)//如果是白底黑字{projectValArry[col]++;}}}Mat verticalProjectionMat(height, width, CV_8UC1);//垂直投影的画布for (int i = 0; i < height; i++){for (int j = 0; j < width; j++){perPixelValue = 255;  //背景设置为白色verticalProjectionMat.at<uchar>(i, j) = perPixelValue;}}for (int i = 0; i < width; i++)//垂直投影直方图{for (int j = 0; j < projectValArry[i]; j++){perPixelValue = 0;  //直方图设置为黑色  verticalProjectionMat.at<uchar>(height - 1 - j, i) = perPixelValue;}}imshow("垂直投影", verticalProjectionMat);cvWaitKey(0);vector<Mat> roiList;//用于储存分割出来的每个字符int startIndex = 0;//记录进入字符区的索引int endIndex = 0;//记录进入空白区域的索引bool inBlock = false;//是否遍历到了字符区内for (int i = 0; i < srcImg.cols; i++)//cols=width{if (!inBlock && projectValArry[i] != 0)//进入字符区{inBlock = true;startIndex = i;}else if (projectValArry[i] == 0 && inBlock)//进入空白区{endIndex = i;inBlock = false;Mat roiImg = srcImg(Range(0, srcImg.rows), Range(startIndex, endIndex + 1));roiList.push_back(roiImg);}}delete[] projectValArry;return roiList;}int main(int argc, char* argv[]){//先进行垂直投影,再进行水平投影分割字符串Mat srcImg = imread("b.png", 0);//读入原图像char szName[30] = { 0 };vector<Mat> b = verticalProjectionMat(srcImg);//先进行垂直投影//垂直投影以后的结果for (int j = 0; j < b.size(); j++){sprintf(szName, "vertical_%d.jpg", j);imshow(szName, b[j]);IplImage img = IplImage(b[j]);cvSaveImage(szName, &img);//保存切分的结果}//////////////////////////////////////////////////////////////////////////for (int i = 0; i < b.size(); i++){vector<Mat> a = horizontalProjectionMat(b[i]);//水平投影sprintf(szName, "%d.jpg", i);for (int j = 0; j < a.size(); j++){imshow(szName, a[j]);IplImage img = IplImage(a[j]);cvSaveImage(szName, &img);//保存切分的结果}}/*vector<Mat> a = horizontalProjectionMat(srcImg);char szName[30] = { 0 };for (int i = 0; i < a.size(); i++){vector<Mat> b = verticalProjectionMat(a[i]);for (int j = 0; j<b.size();j++){sprintf(szName, "E:\\%d.jpg", j);imshow(szName, b[j]);}}*/cvWaitKey(0);getchar();return 0;}



结果


如果只打算看结果的话,可以屏蔽掉垂直投影的输出

1 0
原创粉丝点击