1500字范文,内容丰富有趣,写作好帮手!
1500字范文 > OpenCV 分割斜体文字(包括旋转 垂直投影 水平投影 透视变换等)

OpenCV 分割斜体文字(包括旋转 垂直投影 水平投影 透视变换等)

时间:2019-12-19 07:21:17

相关推荐

OpenCV 分割斜体文字(包括旋转 垂直投影 水平投影 透视变换等)

一,原图

二,分割成行

三,通过旋转,切割后的效果(无透视变换)

四,通过旋转,透视变换,切割后的效果

五,源代码

//初始化透视变换全局变量Mat warpMatrix;//计算透视变换矩阵void InitPersTransfor(){vector<Point> not_a_rect_shape;not_a_rect_shape.push_back(Point(3, 82));not_a_rect_shape.push_back(Point(2, 276));not_a_rect_shape.push_back(Point(234, 191));not_a_rect_shape.push_back(Point(239, 1));// For debugging purposes, draw green lines connecting those points// and save it on diskconst Point* point = &not_a_rect_shape[0];int n = (int)not_a_rect_shape.size();//Mat draw = ImgCut.clone();//polylines(draw, &point, &n, 1, true, Scalar(0, 255, 0), 3, CV_AA);//imwrite("draw.jpg", draw);// topLeft, topRight, bottomRight, bottomLeftcv::Point2f src_vertices[4];src_vertices[0] = not_a_rect_shape[0];src_vertices[1] = not_a_rect_shape[1];src_vertices[2] = not_a_rect_shape[2];src_vertices[3] = not_a_rect_shape[3];Point2f dst_vertices[4];dst_vertices[0] = Point(2, 2);dst_vertices[1] = Point(0, 194);dst_vertices[2] = Point(235, 190);dst_vertices[3] = Point(239, 1);warpMatrix = getPerspectiveTransform(src_vertices, dst_vertices);}//斜体分割void MyCutImageItalic(Mat src, int iImgNO, CString C_SavePath, bool bSave){//--------------旋转------------------------------------------------------double angle = 19;Point2f center(src.cols / 2, src.rows / 2);Mat rot = getRotationMatrix2D(center, angle, 1);Rect bbox = RotatedRect(center, src.size(), angle).boundingRect();rot.at<double>(0, 2) += bbox.width / 2.0 - center.x;rot.at<double>(1, 2) += bbox.height / 2.0 - center.y;//设置选择背景边界颜色:白色 Scalar borderColor = Scalar(255, 255, 255);Mat dst;warpAffine(src, dst, rot, bbox.size(), INTER_LINEAR, BORDER_CONSTANT, borderColor);Mat gray, BinImg;if (dst.channels() == 3){cvtColor(dst, gray, CV_BGR2GRAY); //转换成灰度图}else{gray = dst;}//--------------旋转------------------------------------------------------//--------------垂直投影--------------------------------------------------threshold(gray, BinImg, 166, 255, CV_THRESH_BINARY); //整个图像进行二值化Mat lineImg(1, BinImg.cols, CV_8UC1, cv::Scalar(0, 0, 0)); //生成一维图像,高是1,宽是原图列数lineImg = VerticalProjection(BinImg);//---------------判断峰值的开始结束位置-------------------------vector<int> ivecBegin;//开始vector<int> ivecEnd; //结束int icount = 0; //统计峰值数int ibegin = 666666; //开始位置int iend = 666666; //结束位置int minVal = 2; //判断的基准值int minSpace = 6;//最小间距bool bbegin = false; //判断峰值是否在最左边int value = 0; //图像像素值for (int i = 0; i < lineImg.cols; i++){value = lineImg.at<uchar>(0, i);//=======排除最左边峰值干扰=============if (value > minVal&&i == 0){bbegin = true;}if (value < minVal&&bbegin == true){bbegin = false;}//=======排除最左边峰值干扰=============if (value > minVal && ibegin == 666666 && bbegin == false)//bbegin == false可排除最左边未切割干净的字符{ibegin = i; //开始位置 }else if (value<minVal&&ibegin != 666666 && (i - ibegin)>minSpace){icount++;//统计数加1iend = i;//结束位置ivecBegin.push_back(ibegin);//加入容器ivecEnd.push_back(iend);//加入容器ibegin = 666666; //复位iend = 666666;//复位}else if (value>minVal&&ibegin != 666666 && i == lineImg.cols - 1)//峰值在最右边情况{icount++;//统计数加1iend = i;//结束位置ivecBegin.push_back(ibegin);//加入容器ivecEnd.push_back(iend);//加入容器ibegin = 666666; //复位iend = 666666;//复位}else{}} //for (int i = 0; i < lineImg.cols; i++)//---------------判断峰值的开始结束位置-------------------//--------------垂直投影--------------------------------------------------for (int i = 0; i < ivecEnd.size(); i++){Mat ImgCut = BinImg(Rect(ivecBegin[i] - 1, 0, ivecEnd[i] - ivecBegin[i] + 1, BinImg.rows)); //选择二值化图像部分Mat ImgCutgray = gray(Rect(ivecBegin[i] - 1, 0, ivecEnd[i] - ivecBegin[i] + 1, BinImg.rows));//选择灰度图像部分//-------------------透视变换校正-----------------------------------------------------cv::Mat rotated, rotatedgray;//设置选择背景边界颜色:白色 Scalar borderColor2 = Scalar(255, 255, 255);warpPerspective(ImgCut, rotated, warpMatrix, rotated.size(), INTER_LINEAR, BORDER_CONSTANT, borderColor2);warpPerspective(ImgCutgray, rotatedgray, warpMatrix, rotatedgray.size(), INTER_LINEAR, BORDER_CONSTANT, borderColor2);//-------------------透视变换校正-----------------------------------------------------//-------------------先做一下水平投影,去除多余空白-----------------------------------Mat rotatedCopy;rotated.copyTo(rotatedCopy);Mat HorImg = HorProjection(rotatedCopy); //水平投影int ibeginrow = 0;//开始行int iendrow = 0; //结束行bool bbeginrow = false;bool bendrow = false;bool bHorFengzhi = false; //水平方向是否有峰值for (int i = 0; i < HorImg.rows; i++){if (HorImg.at<uchar>(i, 0) != 0 && bbeginrow == false) //正向搜索{ibeginrow = i;bbeginrow = true;}if (HorImg.at<uchar>(HorImg.rows - i - 1, 0) != 0 && bendrow == false) //反向搜索{iendrow = HorImg.rows - i - 1;bendrow = true;}}Mat imgSave = rotatedgray(Rect(0, ibeginrow, ImgCut.cols, iendrow - ibeginrow + 1));//-------------------先做一下水平投影,去除多余空白-----------------------------------if (bSave == true){CString CTemp;CTemp.Format(_T("%s%d_%d.jpg"), C_SavePath,iImgNO, i + 1);string strImgPath = (CW2A(CTemp.GetString()));imwrite(strImgPath, imgSave);}} //for (int i = 0; i < ivecEnd.size(); i++)}//读取待分割图像bool CCutImageVSDlg::MyClassifiReadImageItalic(){//初始化透视变换InitPersTransfor();CWnd* pWnd = AfxGetMainWnd();//CString C_SavePath, C_readImgPath;int NUM = 0; //读图图片数量pWnd->GetDlgItem(IDC_ImgNum_EDIT)->GetWindowTextW(m_ImgNumVal);//获取控件中的参数值NUM = _wtoi(m_ImgNumVal); //传给全局变量if (NUM == 0){AfxMessageBox(_T("请输入图像数量!"));return false;}Mat image;int iImgNO = 1;CString C_str;int iType = 66;//##########判断文件夹存不存在###########################if (nSel == 0){C_readImgPath = "D:\\sxl\\处理图片\\斜体分割\\1lineImage\\"; //读取图像路径C_SavePath = "D:\\sxl\\处理图片\\斜体分割\\1lineImage处理\\";//------------方便查看结果-------------C_FilePath = C_SavePath;//------------方便查看结果-------------//strPath0.Format(_T("%s\\"), C_Str0);if (!PathFileExists(C_SavePath)){system("md D:\\sxl\\处理图片\\斜体分割\\1lineImage处理\\");}}int icount = 0;int iID = 0;while (iImgNO <= NUM) //{//#############################################CString C_Status;C_Status.Format(_T("正在处理第%d张图,共%d张!"), iImgNO, NUM);pWnd->GetDlgItem(IDC_Status_EDIT)->SetWindowTextW(C_Status);pWnd->UpdateWindow();//#############################################if ((iImgNO-icount*21) == 22){icount++;iID = 0;}iID++;C_str.Format(_T("%s%d_%d.jpg"), C_readImgPath, icount, iID); //读取图像路径string strImgPath = (CW2A(C_str.GetString()));image = imread(strImgPath, 0);//读取图片 if (image.data == 0){AfxMessageBox(_T("没有图片!"));return false;}else{//#####处理图像####################Mat imageCopy;image.copyTo(imageCopy);MyCutImageItalic(image, iImgNO, C_SavePath, true);//#####处理图像####################}iImgNO++;}AfxMessageBox(_T("运行结束!"));return true;}

欢迎扫码关注我的微信公众号

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