1500字范文,内容丰富有趣,写作好帮手!
1500字范文 > OpenCV 实现图片的水平投影与垂直投影 并进行行分割

OpenCV 实现图片的水平投影与垂直投影 并进行行分割

时间:2024-04-24 02:02:15

相关推荐

OpenCV 实现图片的水平投影与垂直投影 并进行行分割

前言:对于印刷体图片来说,进行水平投影和垂直投影可以很快的进行分割,本文在OpenCV中如何进行水平投影和垂直投影通过代码进行说明。

水平投影:二维图像在y轴上的投影

垂直投影:二维图像在x轴上的投影

由于投影的图像需要进行二值化,本文采用积分二值化的方式,对图片进行处理。

具体代码如下:

1 //积分二值化 2 void thresholdIntegral (Mat inputMat, Mat& outputMat) 3 { 4 5int nRows = inputMat.rows; 6int nCols = inputMat.cols; 7 8// create the integral image 9Mat sumMat; 10integral (inputMat, sumMat); 11 12int S = MAX (nRows, nCols) / 8; 13double T = 0.15; 14 15// perform thresholding 16int s2 = S / 2; 17int x1, y1, x2, y2, count, sum; 18 19int* p_y1, *p_y2; 20uchar* p_inputMat, *p_outputMat; 21 22for (int i = 0; i < nRows; ++i) 23{ 24 y1 = i - s2; 25 y2 = i + s2; 26 27 if (y1 < 0) 28 { 29 y1 = 0; 30 } 31 if (y2 >= nRows) 32 { 33 y2 = nRows - 1; 34 } 35 36 p_y1 = sumMat.ptr<int> (y1); 37 p_y2 = sumMat.ptr<int> (y2); 38 p_inputMat = inputMat.ptr<uchar> (i); 39 p_outputMat = outputMat.ptr<uchar> (i); 40 41 for (int j = 0; j < nCols; ++j) 42 { 43 // set the SxS region 44 x1 = j - s2; 45 x2 = j + s2; 46 47 if (x1 < 0) 48 { 49 x1 = 0; 50 } 51 if (x2 >= nCols) 52 { 53 x2 = nCols - 1; 54 } 55 56 count = (x2 - x1)* (y2 - y1); 57 58 // I(x,y)=s(x2,y2)-s(x1,y2)-s(x2,y1)+s(x1,x1) 59 sum = p_y2[x2] - p_y1[x2] - p_y2[x1] + p_y1[x1]; 60 61 if ((int) (p_inputMat[j] * count) < (int) (sum* (1.0 - T))) 62 { 63 p_outputMat[j] = 0; 64 } 65 else 66 { 67 p_outputMat[j] = 255; 68 } 69 } 70} 71 } 72 //垂直方向投影 73 void picshadowx (Mat binary) 74 { 75Mat paintx (binary.size(), CV_8UC1, Scalar (255)); //创建一个全白图片,用作显示 76 77int* blackcout = new int[binary.cols]; 78memset (blackcout, 0, binary.cols * 4); 79 80for (int i = 0; i < binary.rows; i++) 81{ 82 for (int j = 0; j < binary.cols; j++) 83 { 84 if (binary.at<uchar> (i, j) == 0) 85 { 86 blackcout[j]++; //垂直投影按列在x轴进行投影 87 } 88 } 89} 90for (int i = 0; i < binary.cols; i++) 91{ 92 for (int j = 0; j < blackcout[i]; j++) 93 { 94 paintx.at<uchar> (binary.rows-1-j, i) = 0; //翻转到下面,便于观看 95 } 96} 97delete blackcout; 98imshow ("paintx", paintx); 99 100 }101 //水平方向投影并行分割102 void picshadowy (Mat binary)103 { 104 //是否为白色或者黑色根据二值图像的处理得来105Mat painty (binary.size(), CV_8UC1, Scalar (255)); //初始化为全白106 107 //水平投影108 int* pointcount = new int[binary.rows]; //在二值图片中记录行中特征点的个数109memset (pointcount, 0, binary.rows * 4);//注意这里需要进行初始化110 111for (int i = 0; i < binary.rows; i++)112{113 for (int j = 0; j < binary.cols; j++)114 {115 if (binary.at<uchar> (i, j) == 0)116 {117 pointcount[i]++; //记录每行中黑色点的个数 //水平投影按行在y轴上的投影118 }119 }120}121 122for (int i = 0; i < binary.rows; i++)123{124 for (int j = 0; j < pointcount[i]; j++) //根据每行中黑色点的个数,进行循环125 {126 127 painty.at<uchar> (i, j) = 0; 128 }129 130}131 132imshow ("painty", painty);133 134vector<Mat> result;135int startindex = 0;136int endindex = 0;137bool inblock = false; //是否遍历到字符位置138 139for (int i = 0; i < painty.rows; i++)140{141 142 if (!inblock&&pointcount[i] != 0) //进入有字符区域143 {144 inblock = true;145 startindex = i;146 cout << "startindex:" << startindex << endl;147 }148 if (inblock&&pointcount[i] == 0) //进入空白区149 {150 endindex = i;151 inblock = false;152 Mat roi = binary.rowRange (startindex, endindex+1); //从而记录从开始到结束行的位置,即可进行行切分153 result.push_back (roi);154 }155}156 157for (int i = 0; i < result.size(); i++)158{159 Mat tmp = result[i];160 imshow ("test"+to_string (i), tmp);161}162delete pointcount;163 164 }165 int main (int argc, char* argv[])166 {167 168 Mat src = cv::imread ("test.jpg");169 170 if (src.empty())171 {172 cerr << "Problem loading image!!!" << endl;173 return -1;174 }175 176 imshow("in",src);177 178 Mat gray;179 180 if (src.channels() == 3)181 {182 cv::cvtColor (src, gray, CV_BGR2GRAY); 183 }184 else185 {186 gray = src;187 }188189 190 Mat bw2 = Mat::zeros (gray.size(), CV_8UC1);191 thresholdIntegral (gray, bw2);192 193 cv::imshow ("binary integral", bw2);194 195 //picshadowx (bw2);196 picshadowy (bw2);197 waitKey (0);198199return 0;200 }

输入图片:

二值图片:

水平投影:

垂直投影:

行切割:

该处理方法,对印刷体有较好的效果,因为印刷体的行列区分明显,因此可以很快的进行行与列的分割。

by Shawn Chen,.12.13日,晚。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。