多字符直线倾斜旋转校正
对于直线倾斜的成串字符 可以通过 开运算连成一片 在用细化算法 求直线 算出倾斜角度 以此纠正
![](https://images.cnblogs.com/cnblogs_com/xiaomaLV2/201207/20120704153942103.jpg)
// ration1.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "highgui.h"
#include "cv.h"
#include "cxcore.h"
#ifdef DEBUG
#pragma comment(lib," opencv_core231d.lib")
#pragma comment(lib,"opencv_features2d231d.lib")
#pragma comment(lib,"opencv_flann231d.lib")
#pragma comment(lib,"opencv_gpu231d.lib")
#pragma comment(lib,"opencv_highgui231d.lib")
#pragma comment(lib,"opencv_imgproc231d.lib")
#else
#pragma comment(lib,"opencv_core231.lib")
#pragma comment(lib,"opencv_features2d231.lib")
#pragma comment(lib,"opencv_flann231.lib")
#pragma comment(lib,"opencv_gpu231.lib")
#pragma comment(lib,"opencv_highgui231.lib")
#pragma comment(lib,"opencv_imgproc231.lib")
#endif
void cvThin( IplImage* src, IplImage* dst, int iterations)
{
CvSize size = cvGetSize(src);
cvCopy(src, dst);
int n = 0,i = 0,j = 0;
for(n=0; n<iterations; n++)
{
IplImage* t_image = cvCloneImage(dst);
for(i=0; i<size.height; i++)
{
for(j=0; j<size.width; j++)
{
if(CV_IMAGE_ELEM(t_image,byte,i,j)==1)
{
int ap=0;
int p2 = (i==0)?0:CV_IMAGE_ELEM(t_image,byte, i-1, j);
int p3 = (i==0 || j==size.width-1)?0:CV_IMAGE_ELEM(t_image,byte, i-1, j+1);
if (p2==0 && p3==1)
{
ap++;
}
int p4 = (j==size.width-1)?0:CV_IMAGE_ELEM(t_image,byte,i,j+1);
if(p3==0 && p4==1)
{
ap++;
}
int p5 = (i==size.height-1 || j==size.width-1)?0:CV_IMAGE_ELEM(t_image,byte,i+1,j+1);
if(p4==0 && p5==1)
{
ap++;
}
int p6 = (i==size.height-1)?0:CV_IMAGE_ELEM(t_image,byte,i+1,j);
if(p5==0 && p6==1)
{
ap++;
}
int p7 = (i==size.height-1 || j==0)?0:CV_IMAGE_ELEM(t_image,byte,i+1,j-1);
if(p6==0 && p7==1)
{
ap++;
}
int p8 = (j==0)?0:CV_IMAGE_ELEM(t_image,byte,i,j-1);
if(p7==0 && p8==1)
{
ap++;
}
int p9 = (i==0 || j==0)?0:CV_IMAGE_ELEM(t_image,byte,i-1,j-1);
if(p8==0 && p9==1)
{
ap++;
}
if(p9==0 && p2==1)
{
ap++;
}
if((p2+p3+p4+p5+p6+p7+p8+p9)>1 && (p2+p3+p4+p5+p6+p7+p8+p9)<7)
{
if(ap==1)
{
if(!(p2 && p4 && p6))
{
if(!(p4 && p6 && p8))
{
CV_IMAGE_ELEM(dst,byte,i,j)=0;
}
}
}
}
}
}
}
cvReleaseImage(&t_image);
t_image = cvCloneImage(dst);
for(i=0; i<size.height; i++)
{
for(int j=0; j<size.width; j++)
{
if(CV_IMAGE_ELEM(t_image,byte,i,j)==1)
{
int ap=0;
int p2 = (i==0)?0:CV_IMAGE_ELEM(t_image,byte, i-1, j);
int p3 = (i==0 || j==size.width-1)?0:CV_IMAGE_ELEM(t_image,byte, i-1, j+1);
if (p2==0 && p3==1)
{
ap++;
}
int p4 = (j==size.width-1)?0:CV_IMAGE_ELEM(t_image,byte,i,j+1);
if(p3==0 && p4==1)
{
ap++;
}
int p5 = (i==size.height-1 || j==size.width-1)?0:CV_IMAGE_ELEM(t_image,byte,i+1,j+1);
if(p4==0 && p5==1)
{
ap++;
}
int p6 = (i==size.height-1)?0:CV_IMAGE_ELEM(t_image,byte,i+1,j);
if(p5==0 && p6==1)
{
ap++;
}
int p7 = (i==size.height-1 || j==0)?0:CV_IMAGE_ELEM(t_image,byte,i+1,j-1);
if(p6==0 && p7==1)
{
ap++;
}
int p8 = (j==0)?0:CV_IMAGE_ELEM(t_image,byte,i,j-1);
if(p7==0 && p8==1)
{
ap++;
}
int p9 = (i==0 || j==0)?0:CV_IMAGE_ELEM(t_image,byte,i-1,j-1);
if(p8==0 && p9==1)
{
ap++;
}
if(p9==0 && p2==1)
{
ap++;
}
if((p2+p3+p4+p5+p6+p7+p8+p9)>1 && (p2+p3+p4+p5+p6+p7+p8+p9)<7)
{
if(ap==1)
{
if(p2*p4*p8==0)
{
if(p2*p6*p8==0)
{
CV_IMAGE_ELEM(dst, byte,i,j)=0;
}
}
}
}
}
}
}
cvReleaseImage(&t_image);
}
}
void autoCorrection(IplImage * src , int elementx , int elementy)
{
IplImage * dst = cvCreateImage(cvGetSize(src),8,1);
//1. 闭运算连成一片
//创建自定义核
IplConvKernel * element = cvCreateStructuringElementEx(elementx ,elementy,elementx/2,elementy/2,CV_SHAPE_RECT);
cvMorphologyEx(src,dst,NULL,element,CV_MOP_CLOSE);
cvReleaseStructuringElement(&element);
// cvShowImage("close",dst);
//2. 细化
cvThreshold(dst,dst,100,1,CV_THRESH_BINARY);
IplImage * thin = cvCreateImage(cvGetSize(src),8,1);
cvThin(dst,thin,elementy);
cvThreshold(thin,thin,0.5,255,CV_THRESH_BINARY);
//cvShowImage("thin",thin);
// 3 . hough 找直线
CvMemStorage * stroge = cvCreateMemStorage(0);
CvSeq * lines = NULL;
float *fline,fTheta;
int angle;
lines = cvHoughLines2(thin,stroge,CV_HOUGH_STANDARD,2,CV_PI/180,100,0,0);
if (lines->total ==0)
{
return ;
}
fline = (float*)cvGetSeqElem(lines,0);
fTheta = fline[1]; // 过原点与直线垂直的直线与x轴夹角
angle = (int)(fTheta *180/ CV_PI + 0.5);
if (angle >= 90 && angle <= 135)
{
angle = angle -90;
}
else if (angle >0 && angle <= 45)
{
}
else if(angle >135 && angle < 180)
{
//Rotation(pImageData,nPixelFormatSize,nwidthstep,nwidth,nheight,90 - angle);
angle = 90 - angle;
}else if (angle >45 &&angle <90)
{
//Rotation(pImageData,nPixelFormatSize,nwidthstep,nwidth,nheight,angle - 90);
angle = angle -90;
}
cvThreshold(src , src ,100,255 , CV_THRESH_BINARY_INV);
IplImage * ration = cvCreateImage(cvGetSize(src),8,1);
float m[6];
CvMat M = cvMat( 2, 3, CV_32F, m );
CvPoint2D32f pt = cvPoint2D32f(src->width/2.0, src->height/2.0);
cv2DRotationMatrix(pt, angle, 1.0, &M);
cvWarpAffine(src,ration,&M,CV_INTER_AREA |CV_WARP_FILL_OUTLIERS,cvScalarAll(255));
memcpy(src->imageData,ration->imageData,src->imageSize);
//cvShowImage("ration",ration);
cvReleaseImage(&ration);
cvReleaseMemStorage(&stroge);
cvReleaseImage(&thin);
cvReleaseImage(&dst);
}
int _tmain(int argc, _TCHAR* argv[])
{
IplImage * src =cvLoadImage("E7.jpg",CV_LOAD_IMAGE_GRAYSCALE);
cvShowImage("src",src);
cvThreshold(src, src, 0,255,CV_THRESH_OTSU);
// 要求背景为黑色纠正物体为白色
cvThreshold(src , src , 100,255 , CV_THRESH_BINARY_INV);
autoCorrection(src,70,70);
cvShowImage("ration",src);
cvWaitKey(-1);
getchar();
return 0;
}
//
#include "stdafx.h"
#include "highgui.h"
#include "cv.h"
#include "cxcore.h"
#ifdef DEBUG
#pragma comment(lib," opencv_core231d.lib")
#pragma comment(lib,"opencv_features2d231d.lib")
#pragma comment(lib,"opencv_flann231d.lib")
#pragma comment(lib,"opencv_gpu231d.lib")
#pragma comment(lib,"opencv_highgui231d.lib")
#pragma comment(lib,"opencv_imgproc231d.lib")
#else
#pragma comment(lib,"opencv_core231.lib")
#pragma comment(lib,"opencv_features2d231.lib")
#pragma comment(lib,"opencv_flann231.lib")
#pragma comment(lib,"opencv_gpu231.lib")
#pragma comment(lib,"opencv_highgui231.lib")
#pragma comment(lib,"opencv_imgproc231.lib")
#endif
void cvThin( IplImage* src, IplImage* dst, int iterations)
{
CvSize size = cvGetSize(src);
cvCopy(src, dst);
int n = 0,i = 0,j = 0;
for(n=0; n<iterations; n++)
{
IplImage* t_image = cvCloneImage(dst);
for(i=0; i<size.height; i++)
{
for(j=0; j<size.width; j++)
{
if(CV_IMAGE_ELEM(t_image,byte,i,j)==1)
{
int ap=0;
int p2 = (i==0)?0:CV_IMAGE_ELEM(t_image,byte, i-1, j);
int p3 = (i==0 || j==size.width-1)?0:CV_IMAGE_ELEM(t_image,byte, i-1, j+1);
if (p2==0 && p3==1)
{
ap++;
}
int p4 = (j==size.width-1)?0:CV_IMAGE_ELEM(t_image,byte,i,j+1);
if(p3==0 && p4==1)
{
ap++;
}
int p5 = (i==size.height-1 || j==size.width-1)?0:CV_IMAGE_ELEM(t_image,byte,i+1,j+1);
if(p4==0 && p5==1)
{
ap++;
}
int p6 = (i==size.height-1)?0:CV_IMAGE_ELEM(t_image,byte,i+1,j);
if(p5==0 && p6==1)
{
ap++;
}
int p7 = (i==size.height-1 || j==0)?0:CV_IMAGE_ELEM(t_image,byte,i+1,j-1);
if(p6==0 && p7==1)
{
ap++;
}
int p8 = (j==0)?0:CV_IMAGE_ELEM(t_image,byte,i,j-1);
if(p7==0 && p8==1)
{
ap++;
}
int p9 = (i==0 || j==0)?0:CV_IMAGE_ELEM(t_image,byte,i-1,j-1);
if(p8==0 && p9==1)
{
ap++;
}
if(p9==0 && p2==1)
{
ap++;
}
if((p2+p3+p4+p5+p6+p7+p8+p9)>1 && (p2+p3+p4+p5+p6+p7+p8+p9)<7)
{
if(ap==1)
{
if(!(p2 && p4 && p6))
{
if(!(p4 && p6 && p8))
{
CV_IMAGE_ELEM(dst,byte,i,j)=0;
}
}
}
}
}
}
}
cvReleaseImage(&t_image);
t_image = cvCloneImage(dst);
for(i=0; i<size.height; i++)
{
for(int j=0; j<size.width; j++)
{
if(CV_IMAGE_ELEM(t_image,byte,i,j)==1)
{
int ap=0;
int p2 = (i==0)?0:CV_IMAGE_ELEM(t_image,byte, i-1, j);
int p3 = (i==0 || j==size.width-1)?0:CV_IMAGE_ELEM(t_image,byte, i-1, j+1);
if (p2==0 && p3==1)
{
ap++;
}
int p4 = (j==size.width-1)?0:CV_IMAGE_ELEM(t_image,byte,i,j+1);
if(p3==0 && p4==1)
{
ap++;
}
int p5 = (i==size.height-1 || j==size.width-1)?0:CV_IMAGE_ELEM(t_image,byte,i+1,j+1);
if(p4==0 && p5==1)
{
ap++;
}
int p6 = (i==size.height-1)?0:CV_IMAGE_ELEM(t_image,byte,i+1,j);
if(p5==0 && p6==1)
{
ap++;
}
int p7 = (i==size.height-1 || j==0)?0:CV_IMAGE_ELEM(t_image,byte,i+1,j-1);
if(p6==0 && p7==1)
{
ap++;
}
int p8 = (j==0)?0:CV_IMAGE_ELEM(t_image,byte,i,j-1);
if(p7==0 && p8==1)
{
ap++;
}
int p9 = (i==0 || j==0)?0:CV_IMAGE_ELEM(t_image,byte,i-1,j-1);
if(p8==0 && p9==1)
{
ap++;
}
if(p9==0 && p2==1)
{
ap++;
}
if((p2+p3+p4+p5+p6+p7+p8+p9)>1 && (p2+p3+p4+p5+p6+p7+p8+p9)<7)
{
if(ap==1)
{
if(p2*p4*p8==0)
{
if(p2*p6*p8==0)
{
CV_IMAGE_ELEM(dst, byte,i,j)=0;
}
}
}
}
}
}
}
cvReleaseImage(&t_image);
}
}
void autoCorrection(IplImage * src , int elementx , int elementy)
{
IplImage * dst = cvCreateImage(cvGetSize(src),8,1);
//1. 闭运算连成一片
//创建自定义核
IplConvKernel * element = cvCreateStructuringElementEx(elementx ,elementy,elementx/2,elementy/2,CV_SHAPE_RECT);
cvMorphologyEx(src,dst,NULL,element,CV_MOP_CLOSE);
cvReleaseStructuringElement(&element);
// cvShowImage("close",dst);
//2. 细化
cvThreshold(dst,dst,100,1,CV_THRESH_BINARY);
IplImage * thin = cvCreateImage(cvGetSize(src),8,1);
cvThin(dst,thin,elementy);
cvThreshold(thin,thin,0.5,255,CV_THRESH_BINARY);
//cvShowImage("thin",thin);
// 3 . hough 找直线
CvMemStorage * stroge = cvCreateMemStorage(0);
CvSeq * lines = NULL;
float *fline,fTheta;
int angle;
lines = cvHoughLines2(thin,stroge,CV_HOUGH_STANDARD,2,CV_PI/180,100,0,0);
if (lines->total ==0)
{
return ;
}
fline = (float*)cvGetSeqElem(lines,0);
fTheta = fline[1]; // 过原点与直线垂直的直线与x轴夹角
angle = (int)(fTheta *180/ CV_PI + 0.5);
if (angle >= 90 && angle <= 135)
{
angle = angle -90;
}
else if (angle >0 && angle <= 45)
{
}
else if(angle >135 && angle < 180)
{
//Rotation(pImageData,nPixelFormatSize,nwidthstep,nwidth,nheight,90 - angle);
angle = 90 - angle;
}else if (angle >45 &&angle <90)
{
//Rotation(pImageData,nPixelFormatSize,nwidthstep,nwidth,nheight,angle - 90);
angle = angle -90;
}
cvThreshold(src , src ,100,255 , CV_THRESH_BINARY_INV);
IplImage * ration = cvCreateImage(cvGetSize(src),8,1);
float m[6];
CvMat M = cvMat( 2, 3, CV_32F, m );
CvPoint2D32f pt = cvPoint2D32f(src->width/2.0, src->height/2.0);
cv2DRotationMatrix(pt, angle, 1.0, &M);
cvWarpAffine(src,ration,&M,CV_INTER_AREA |CV_WARP_FILL_OUTLIERS,cvScalarAll(255));
memcpy(src->imageData,ration->imageData,src->imageSize);
//cvShowImage("ration",ration);
cvReleaseImage(&ration);
cvReleaseMemStorage(&stroge);
cvReleaseImage(&thin);
cvReleaseImage(&dst);
}
int _tmain(int argc, _TCHAR* argv[])
{
IplImage * src =cvLoadImage("E7.jpg",CV_LOAD_IMAGE_GRAYSCALE);
cvShowImage("src",src);
cvThreshold(src, src, 0,255,CV_THRESH_OTSU);
// 要求背景为黑色纠正物体为白色
cvThreshold(src , src , 100,255 , CV_THRESH_BINARY_INV);
autoCorrection(src,70,70);
cvShowImage("ration",src);
cvWaitKey(-1);
getchar();
return 0;
}
作者: 小马_xiao
出处:http://www.cnblogs.com/xiaomaLV2/>
关于作者:专注halcon\opencv\机器视觉
本文版权归作者,未经作者同意必须保留此段声明,且在文章页面明显位置给出 原文链接