#include "stdio.h" #include "cv.h" #include "cxcore.h" #include "highgui.h" void main(int argc, char* argv[]) { IplImage *src=cvLoadImage("test.jpg",1);//原图 IplImage *process=cvCreateImage(cvGetSize(src),IPL_DEPTH_8U,1); IplImage *binaryimage=cvCreateImage(cvGetSize(src),IPL_DEPTH_8U,1);//二值图 cvNamedWindow("src",1); cvShowImage("src",src); cvCvtColor(src,process,CV_BGRA2GRAY);//转化为灰度图 CvMemStorage* storage = NULL; CvSeq* lines = NULL; storage = cvCreateMemStorage(0); cvThreshold(process,process,220,255,CV_THRESH_BINARY_INV); cvCopy( process,binaryimage);//转化为二值图并且备份到binaryimage cvNamedWindow("binaryimage",1); cvShowImage("binaryimage",binaryimage); //Hough直线检测,采用标准霍夫变换 lines = cvHoughLines2( process, storage, CV_HOUGH_STANDARD, 1, CV_PI/180, 190, 0, 0 ); cvSet(src,cvScalar(255,255,255));//将原图清空,绘制出检测到的直线 int i,j; float rho, theta; for( i = 0; i < lines->total; i++ ) { float* line = (float*)cvGetSeqElem(lines, i); rho = line[0]; theta = line[1]; CvPoint pt1, pt2; double a = cos(theta), b = sin(theta); if( fabs(b) < 0.001 ) { pt1.x = pt2.x = cvRound(rho); pt1.y = 0; pt2.y = src->height; } else if( fabs(a) < 0.001 ) { pt1.y = pt2.y = cvRound(rho); pt1.x = 0; pt2.x = src->width; } else { pt1.x = 0; pt1.y = cvRound(rho/b); pt2.x = cvRound(rho/a); pt2.y = 0; } int bb = rand() & 255, gg = rand() & 255, rr = rand() & 255; cvLine( src, pt1, pt2, CV_RGB(rr,gg,bb), 1, 8 ); } //按照theta排序 for (i = 0; i < lines->total; i++) { for (j = i; j < lines->total; j++) { float* line1 = (float*)cvGetSeqElem(lines, i); float* line2 = (float*)cvGetSeqElem(lines, j); if (line1[1]>line2[1]) { rho=line2[0]; theta=line2[1]; line2[0]=line1[0]; line2[1]=line1[1]; line1[0]=rho; line1[1]=theta; } } } //统计水平线与竖直线的条数 int HNo=0,VNo=0; for (i = 0; i < lines->total; i++) { float* line = (float*)cvGetSeqElem(lines, i); if (line[1]==0) { VNo++; } } HNo=lines->total-VNo; printf("直线的条数共计%d,水平线%d条,竖直线%d条\n",lines->total,HNo,VNo); //按照rho排序,先排竖直线 for (i = 0; i < VNo; i++) { for (j = i; j < VNo; j++) { float* line1 = (float*)cvGetSeqElem(lines, i); float* line2 = (float*)cvGetSeqElem(lines, j); if (line1[0]>line2[0]) { rho=line2[0]; theta=line2[1]; line2[0]=line1[0]; line2[1]=line1[1]; line1[0]=rho; line1[1]=theta; } } } //后排水平线 for (i = VNo; i < lines->total; i++) { for (j = i; j < lines->total; j++) { float* line1 = (float*)cvGetSeqElem(lines, i); float* line2 = (float*)cvGetSeqElem(lines, j); if (line1[0]>line2[0]) { rho=line2[0]; theta=line2[1]; line2[0]=line1[0]; line2[1]=line1[1]; line1[0]=rho; line1[1]=theta; } } } //输出排序后的结果 for( i = 0; i < lines->total; i++ ) { float* line = (float*)cvGetSeqElem(lines, i); printf("直线%d:rho=%f,theta=%f\n",i,line[0],line[1]); } //逐个扫描各个矩形区域 for (i=0;i<17;i++) { for (j=0;j<5;j++) { int x1,y1,x2,y2,reduce; reduce=2; float* line = (float*)cvGetSeqElem(lines,2+j); x1=(int)line[0]+reduce; if (j==4) { x2=src->width-reduce; } else { line = (float*)cvGetSeqElem(lines,3+j); x2=(int)line[0]-reduce; } line = (float*)cvGetSeqElem(lines,VNo+1+i); y1=(int)line[0]+reduce; if (i==16) { y2=src->height-reduce; } else { line = (float*)cvGetSeqElem(lines,VNo+2+i); y2=(int)line[0]-reduce; } int sum=0; for (int m=x1;m<=x2;m++) { for (int n=y1;n<=y2;n++) { if (CV_IMAGE_ELEM(binaryimage,unsigned char,n,m)==255) { sum++; } } } //面积值大于50则认为存在对号 if (sum>50) { cvSetImageROI(src,cvRect(x1,y1,x2-x1,y2-y1)); int bb = rand() & 0xffffff; cvFillImage(src,bb); cvResetImageROI(src); break; } } printf("部门%d的等次:",i+1); switch(j) { case 0: printf("好\n"); break; case 1: printf("较好\n"); break; case 2: printf("一般\n"); break; case 3: printf("差\n"); break; case 4: printf("极差\n"); break; default: printf("error\n"); break; } } cvNamedWindow( "result", 1 ); cvShowImage( "result", src); cvSaveImage("result.jpg",src); cvWaitKey(0); cvDestroyAllWindows(); cvReleaseImage(&src); cvReleaseImage(&process); cvReleaseImage(&binaryimage); }
用opencv2改写后代码如下:
#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include "cv.h"
#include "cxcore.h"
#include "highgui.h"
using namespace std;
using namespace cv;
int main()
{
Mat srcImage,binImage,tempImage;
srcImage=imread("test.jpg");//原图像
namedWindow("原图");
imshow("原图",srcImage);
cvtColor(srcImage,tempImage,CV_BGRA2GRAY);//原图转化为灰度图
threshold(tempImage,tempImage,220,255,CV_THRESH_BINARY_INV);//转化为二值图
tempImage.copyTo(binImage);//把二值图拷贝到binImage中
namedWindow("二值图");
imshow("二值图",binImage);
//Hough直线检测,采用标准霍夫变换
vector<Vec2f> lines;
HoughLines(tempImage,lines,1,CV_PI/180,190,0,0);
//绘制检测到的直线
size_t i,j;
float rho,theta;
for(i=0;i<lines.size();i++)
{
rho=lines[i][0];
theta=lines[i][1];
Point pt1,pt2;
double a=cos(theta);
double b=sin(theta);
if(fabs(b)<0.001)//fabs(b)求b的绝对值
{
pt1.x=pt2.x=cvRound(rho);
pt1.y=0;
pt2.y=srcImage.size().height;
}
else if(fabs(a)<0.001 )
{
pt1.y = pt2.y = cvRound(rho);
pt1.x = 0;
pt2.x = srcImage.size().width;
}
else
{
pt1.x = 0;
pt1.y = cvRound(rho/b);
pt2.x = cvRound(rho/a);
pt2.y = 0;
}
int bb = rand() & 255, gg = rand() & 255, rr = rand() & 255;
line(srcImage,pt1, pt2, Scalar(0,255,255), 1, 8 );
}
//按照theta排序
for (i = 0; i <lines.size(); i++)//冒泡排序
{
for (j = i; j <lines.size(); j++)
{
if (lines[i][1]>lines[j][1])
{
rho=lines[j][0];
lines[j][0]=lines[i][0];
lines[i][0]=rho;
theta=lines[j][1];
lines[j][1]=lines[i][1];
lines[i][1]=theta;
}
}
}
//统计水平线与竖直线的条数
int HNo=0,VNo=0;
for (i = 0; i <lines.size(); i++)
{
if (lines[i][1]==0)
{
VNo++; //竖线
}
}
HNo=lines.size()-VNo;//水平线
printf("直线的条数共计%d,水平线%d条,竖直线%d条\n",lines.size(),HNo,VNo);
//按照rho排序,先排竖直线
for (i = 0; i < VNo; i++)
{
for (j = i; j < VNo; j++)
{
if (lines[i][0]>lines[j][0])
{
rho=lines[j][0];
lines[j][0]=lines[i][0];
lines[i][0]=rho;
theta=lines[j][1];
lines[j][1]=lines[i][1];
lines[i][1]=theta;
}
}
}
//后排水平线
for (i = VNo; i <lines.size(); i++)
{
for (j = i; j <lines.size(); j++)
{
if (lines[i][0]>lines[j][0])
{
rho=lines[j][0];
lines[j][0]=lines[i][0];
lines[i][0]=rho;
theta=lines[j][1];
lines[j][1]=lines[i][1];
lines[i][1]=theta;
}
}
}
//输出排序后的结果
for( i = 0; i <lines.size(); i++ )
{
printf("直线%d:rho=%f,theta=%f\n",i,lines[i][0],lines[i][1]);
}
//逐个扫描各个矩形区域
for (i=0;i<17;i++)//代表水平线
{
for (j=0;j<5;j++)//j代表竖线
{
int x1,y1,x2,y2,reduce;
reduce=2;
x1=(int)lines[2+j][0]+reduce;
if (j==4)
{
x2=srcImage.size().width-reduce;
}
else
{
x2=(int)lines[3+j][0]-reduce;
}
y1=(int)lines[VNo+1+i][0]+reduce;
if (i==16)
{
y2=srcImage.size().height-reduce;
}
else
{
y2=(int)lines[VNo+2+i][0]-reduce;
}
int sum=0;
for (int m=x1;m<=x2;m++)//遍历矩形的像素==255?x表示列
{
for (int n=y1;n<=y2;n++)//y代表的高度,即行
{
uchar *data=binImage.ptr<uchar>(n);//通过n取到每行的首地址
if (data[m]==255)
{
sum++;
}
}
}
//cout<<x1<<" "<<y1<<" "<<x2<<" "<<y2<<endl;//调试程序
//面积值大于50则认为存在对号
if (sum>50) //判断矩形里面的
{
int bb = rand() & 0xffffff;
rectangle(srcImage,Point(x1,y1),Point(x2,y2),Scalar(0,255,0),CV_FILLED );
break;
}
}
printf("部门%d的等次:",i+1);
switch(j)
{
case 0:
printf("好\n");
break;
case 1:
printf("较好\n");
break;
case 2:
printf("一般\n");
break;
case 3:
printf("差\n");
break;
case 4:
printf("极差\n");
break;
default:
printf("error\n");
break;
}
}//for循环结束
namedWindow("result");
imshow("result",srcImage);
imwrite("result.jpg",srcImage);
waitKey();
return 0;
}