图像基本变换


//学习OPENCV第6章 图像变换
//霍夫线检测\圆检测
//仿射变换、透射变换、对数极坐标变换

#include<stdio.h>
#include<cv.h>
#include<highgui.h>
#include<stdio.h>
#include<opencv2/legacy/legacy.hpp>
#include<math.h>
#define affine 

char* HOUGH_TYPE = "CV_HOUGH_PROBABILISTIC";//CV_HOUGH_PROBABILISTIC/CV_HOUGH_STANDARD
//CV_HOUGH_STANDARD模式下,绘制直线有问题

int main(int argc, char** argv) 
{
	//-------------------------------------------------------------------
	//霍夫线检测cvHoughLines2
	//http://www.cnblogs.com/justiner/archive/2011/12/20/2294614.html
	const char* filename = "D:\\AI_Proj\\OPENCV\\dog.jpg";
	//cvLoadImage参数2表示是否加载有颜色的图像,0表示单通道图像
    IplImage* src = cvLoadImage(filename,0);
    IplImage* dst = NULL;
    IplImage* color_dst = NULL;
	//保存结果的位置指针
    CvMemStorage* storage = cvCreateMemStorage(0);
    CvSeq* lines = 0;
    int i;
    if(!src)
        return -1;
 
    dst = cvCreateImage(cvGetSize(src),8,1);
    color_dst = cvCreateImage(cvGetSize(src),8,3);
	//canny算子P173
    cvCanny(src,//输入图像,为单通道图像
			dst,//输出灰度图(2值化边缘)
			100,//下限阈值,小于此像素被抛弃
			200,//上限阈值,像素梯度高于此阈值为边缘
			3);//算子大小
	
	//cvCvtColor,颜色空间转换函数
	//可以实现RGB颜色向HSV,HSI等颜色空间的转换,也可以转换为灰度图像
    cvCvtColor(dst,color_dst,CV_GRAY2BGR);
	
	cvNamedWindow("src",1);
	cvNamedWindow("dst",1);
	cvNamedWindow("color_dst",1);
	cvShowImage("src",src);
	cvShowImage("dst",dst);
	cvShowImage("color_dst",color_dst);
	cvWaitKey();
	cvDestroyWindow("src");
	cvDestroyWindow("dst");
	cvDestroyWindow("color_dst");
	
	//hough线变换P175
	if(HOUGH_TYPE == "CV_HOUGH_STANDARD")
	{
		//返回指向内存块中的序列指针
		lines = cvHoughLines2(dst,//输入Image,8位二值化图像
							  storage,//保存结果位置的指针,此处为内存块
							  CV_HOUGH_STANDARD,//标准霍夫变换
							  1,//设置直线所需要的分辨率:分别表示像素个数与弧度
							  CV_PI/180,
							  100,//阈值认定一条直线时在累计平面中必须达到的值
							  0,
							  0);
		
		for(i = 0;i < MIN(lines->total,100);i++)
		{
			float* line = (float*)cvGetSeqElem(lines,i);//从序列中得到每一条直线或线段
			float rho = line[0];
			float theta = line[1];
			CvPoint pt1, pt2;
			double a = cos(theta), b = sin(theta);
			if(fabs(a)<0.001)
			{
				pt1.x = pt2.x = cvRound(rho);
				pt1.y = 0;
				pt2.y = color_dst->height;
			}
			else if(fabs(b)<0.001)
			{
				pt1.y = pt2.y = cvRound(rho);  
                pt1.x = 0;  
                pt2.x = color_dst->width;
			}
			else  
            {  
                pt1.x = 0;  
                pt1.y = cvRound(rho/b);  
                pt2.x = cvRound(rho/a);  
                pt2.y = 0;  
            }  
  
			cvLine(color_dst,pt1,pt2,CV_RGB(255,0,0),1,8);
			/*
			double x0 = a*rho, y0 = b*rho;
			pt1.x = cvRound(x0 + 1000*(-b));
			pt1.y = cvRound(y0 + 1000*(a));
			pt2.x = cvRound(x0 - 1000*(-b));
			pt2.y = cvRound(y0 - 1000*(a));*/
			//OPENCV绘制连接两个点的线段函数原型
			//cvLine(color_dst,pt1,pt2,CV_RGB(255,0,0),3,CV_AA,0);
		}
	}
	else 
		if(HOUGH_TYPE == "CV_HOUGH_PROBABILISTIC")
		{
			lines = cvHoughLines2(dst,storage,CV_HOUGH_PROBABILISTIC,1,CV_PI/180,50,
								  50,//将要返回的线段的最小长度
								  15);//一条直线上分离线段不能连成一条直线的分隔像素点
			for(i = 0;i < lines->total;i++ )
			{
				CvPoint* line = (CvPoint*)cvGetSeqElem(lines,i);
				cvLine(color_dst,line[0],line[1],CV_RGB(255,0,0),3,CV_AA,0);
			}
		}
   
    cvNamedWindow("Source",1);
    cvShowImage("Source",src);
    cvNamedWindow("Hough",1);
    cvShowImage("Hough",color_dst);
		
    cvWaitKey(0);
	cvReleaseImage(&src);
	cvReleaseImage(&color_dst);
	cvDestroyWindow("Source");
	cvDestroyWindow("Hough");
	
	//-------------------------------------------------------------------
	//霍夫圆检测 P182
	IplImage* image = cvLoadImage("D:\\AI_Proj\\OPENCV\\stuff.jpg",CV_LOAD_IMAGE_GRAYSCALE);
	IplImage* src1 = cvLoadImage("D:\\AI_Proj\\OPENCV\\stuff.jpg"); //Changed for prettier show in color
	CvMemStorage* storage1 = cvCreateMemStorage(0);
	cvSmooth(image,image,CV_GAUSSIAN,5,5);
	
	//参数不同,结果显示有很大不同
	CvSeq* results = cvHoughCircles(image,//不需要cvCanny,内部调用cvSobel,计算每个像素梯度的方向,提供更加普通的灰度图
									storage1,//
									CV_HOUGH_GRADIENT,//
									4,//累加器图像的分辨率,>=1
									image->width/10,//2个不同圆之间的最小距离
									120,//边缘阈值
									80,//累加器阈值
									10,//圆半径最小值
									80);//半径最大值
									
	for(int i = 0;i < results->total;i++ ) 
	{
		float* p = (float*)cvGetSeqElem(results,i);
		CvPoint pt = cvPoint(cvRound(p[0]),cvRound(p[1]));
		cvCircle(src1,pt,cvRound(p[2]),CV_RGB(0xff,0,0));
	}
	
	cvNamedWindow("cvHoughCircles",1);
	cvShowImage("cvHoughCircles",src1);
	cvWaitKey(0);
	cvReleaseImage(&src1);
	cvDestroyWindow("cvHoughCircles");
	
	cvWaitKey();
	
	//-------------------------------------------------------------------
	//仿射变换:稠密仿射变换p187
	//http://blog.csdn.net/lxy201700/article/details/19689407
	//像素必须是稠密表现形式:意味着图像扭曲必须进行一些插值运算以使输出图像平滑并且看起来自然
	CvPoint2D32f srcTri[3], dstTri[3]; //
	CvMat* rot_mat = cvCreateMat(2,3,CV_32FC1);
	CvMat* warp_mat = cvCreateMat(2,3,CV_32FC1);
	IplImage *src2, *dst2,*dst21;
	
	src2=cvLoadImage("D:\\AI_Proj\\OPENCV\\dog.jpg",1); 
	
	dst2 = cvCloneImage(src2);
	dst2->origin = src2->origin;
	cvZero(dst2);
	
	dst21 = cvCloneImage(src2);
	dst21->origin = src2->origin;
	cvZero(dst21);
	
	//COMPUTE WARP MATRIX P188
	//src Top left
	srcTri[0].x = 0; 
	srcTri[0].y = 0;
	//src Top right
	srcTri[1].x = src2->width - 1; 		
	srcTri[1].y = 0;
	//src Bottom left
	srcTri[2].x = 0;         
	srcTri[2].y = src2->height - 1;
	
	//具体映射有dst决定
	//dst Top left
	dstTri[0].x = src2->width*0.0;    
	dstTri[0].y = src2->height*0.33;
	//dst Top right
	dstTri[1].x = src2->width*0.85; 
	dstTri[1].y = src2->height*0.25;
	//dst Bottom left
	dstTri[2].x = src2->width*0.15; 
	dstTri[2].y = src2->height*0.7;
	
	//由三对点计算仿射变换,生成映射矩阵
	//输入图像的三角形顶点坐标/输出图像的相应的三角形顶点坐标/指向2×3输出矩阵的指针
	cvGetAffineTransform(srcTri,dstTri,warp_mat);
	
	//对图像做仿射变换:输入输出矩阵、变换矩阵
	cvWarpAffine(src2,dst2,warp_mat);
	cvCopy(dst2,src2);
		
	//计算map_matrix的第二种方法:cv2DRotationMatrix
	//计算围绕任意点旋转的映射矩阵和一个可选择的尺度
	CvPoint2D32f center = cvPoint2D32f(src2->width/2,src2->height/2);
	double angle = -50.0;//旋转角度
	double scale = 0.6;//缩放尺度
	//计算围绕center点的旋转的映射矩阵,以及一个可选的尺度
	//输出映射矩阵rot_mat
	cv2DRotationMatrix(center,angle,scale,rot_mat);
	cvWarpAffine(src2,dst21,rot_mat);
	
	//DO THE TRANSFORM:
	cvNamedWindow("Affine_Transform1",1);
	cvShowImage("Affine_Transform1",dst2);
	cvNamedWindow("Affine_Transform2",1);
	cvShowImage("Affine_Transform2",dst21);
	cvWaitKey();

	cvReleaseImage(&dst2);
	cvReleaseImage(&dst21);
	cvReleaseMat(&rot_mat);
	cvReleaseMat(&warp_mat);
	cvDestroyWindow("Affine_Transform1");
	cvDestroyWindow("Affine_Transform2");
	cvWaitKey();
	
	//-------------------------------------------------------------------	
	//透视变换:采用4个点映射
	CvPoint2D32f srcQuad[4], dstQuad[4];
	CvMat* warp_matrix = cvCreateMat(3,3,CV_32FC1);//映射矩阵必须为3x3
	IplImage *src3, *dst3;
	if(((src3=cvLoadImage("D:\\AI_Proj\\OPENCV\\dog.jpg",1)) != 0))
	{
		dst3 = cvCloneImage(src3);
		dst3->origin = src3->origin;
		cvZero(dst3);
		
		//src Top left
		srcQuad[0].x = 0;           
		srcQuad[0].y = 0;
		//src Top right
		srcQuad[1].x = src3->width - 1;  
		srcQuad[1].y = 0;
		//src Bottom left
		srcQuad[2].x = 0;           
		srcQuad[2].y = src3->height - 1;
		//src Bot right
		srcQuad[3].x = src3->width - 1;  
		srcQuad[3].y = src3->height - 1;

		//dst Top left
		dstQuad[0].x = src3->width*0.05;  
		dstQuad[0].y = src3->height*0.33;
		//dst Top right
		dstQuad[1].x = src3->width*0.9;  
		dstQuad[1].y = src3->height*0.25;
		//dst Bottom left
		dstQuad[2].x = src3->width*0.2;  
		dstQuad[2].y = src3->height*0.7;  
		//dst Bot right		
		dstQuad[3].x = src3->width*0.8;  
		dstQuad[3].y = src3->height*0.9;
		
		//计算透视映射矩阵
		cvGetPerspectiveTransform(srcQuad,dstQuad,warp_matrix);
		cvWarpPerspective(src3,dst3,warp_matrix);
		cvNamedWindow("Perspective_Warp",1);
		cvShowImage( "Perspective_Warp", dst3 );
		cvNamedWindow("src",1);
		cvShowImage( "src", src3 );
		cvWaitKey();
	}
	cvReleaseImage(&dst3);
	cvReleaseImage(&src3);
	cvReleaseMat(&warp_matrix);
	cvDestroyWindow("Perspective_Warp");
	cvDestroyWindow("src");
	cvWaitKey();
	
	//-------------------------------------------------------------------	
	//cvLogPolar:对数极坐标转换 P198
	//用于物体识别的是检测物体周围的而一些关键点:
	//利用关键点中心-->将其作为对数极坐标中心-->创建局部特征
	IplImage* src4;
	double scaler; //受scaler影响大
    if(((src4=cvLoadImage("D:\\AI_Proj\\OPENCV\\dog.jpg",1)) != 0 ))
    {
		scaler = 25; //atof(argv[2]);
        IplImage* dst = cvCreateImage(cvGetSize(src4),8,3);
        IplImage* src5 = cvCreateImage(cvGetSize(src4),8,3);
        cvLogPolar(src4,dst, //单通道/三通道,彩色/灰度图像
				   cvPoint2D32f(src4->width/2,src4->height/2),//对数极坐标变换中心 
                   scaler,//缩放因子,应该事先设置使得ROI区域占主导
				   CV_INTER_LINEAR+CV_WARP_FILL_OUTLIERS);//插值方式

		cvLogPolar(dst,src5,cvPoint2D32f(src4->width/2,src4->height/2),
                    scaler,CV_INTER_LINEAR+CV_WARP_INVERSE_MAP);
					
        cvNamedWindow("src",1);
        cvShowImage("src",src4);
		cvNamedWindow("log-polar",1);
        cvShowImage("log-polar",dst);
        cvNamedWindow("inverse log-polar",1);
        cvShowImage("inverse log-polar",src5);
        cvWaitKey();
		cvReleaseImage(&src4);
		cvReleaseImage(&dst);
		cvReleaseImage(&src5);
		cvDestroyWindow("src");
		cvDestroyWindow("log-polar");
		cvDestroyWindow("inverse log-polar");
    }
	
	cvWaitKey();
	
	
	return 0;
	
}


效果图

canny算子边缘检测


hough线检测


hough圆检测


三点仿射变换


4点透视变换



对数极坐标变换与复原



继续学习傅里叶和DCT

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值