天天看点

opencv——仿射变换的实现

先放代码

这版的代码有点错误,里面的指针分配了内存以后没有释放,有可能会造成内存泄漏

问题原因已经找到了,现在有点累,休息一下。。。

大概说一下吧,主要是因为越界的问题

比如说反变换到输入图像的时候,正确范围应该是(0,in.rows-1)而不是(0,in.rows)

果然,这一版的函数还是有bug,图像的平移参数只能是正整数。。。正在修改中。。。

而且函数接口太次,只能实现CV_8UC1类型的图像的仿射变换

准备改进一下,同时实现CV_32FC1类型的图像的变换

// affine.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/features2d/features2d.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/legacy/legacy.hpp>
#include <iostream>
#include <vector>

using namespace cv;
using namespace std;

void imgaffine(cv::Mat in,cv::Mat out,cv::Mat matrix);


	
// 123.cpp : 定义控制台应用程序的入口点。
//



int _tmain(int argc, _TCHAR* argv[])
{

	cv::Mat a=imread("lena.bmp");
	cv::cvtColor(a,a,CV_RGB2GRAY);
	cv::Mat matrix(1,7,CV_32F);
	float* data_t=matrix.ptr<float>(0);
	data_t[0]=5;
	data_t[1]=10;
	data_t[2]=10;
	data_t[3]=0.8;
	data_t[4]=0.8;
	data_t[5]=0;
	data_t[6]=0;

	float theta=data_t[0]*3.1415926/180;
	int	  dx   =data_t[1];
	int	  dy   =data_t[2];
	float sx   =data_t[3];
	float sy   =data_t[4];
	int	  shx  =data_t[5];
	int	  shy  =data_t[6];

	int m1=a.rows;
	int n1=a.cols;
	float cx1,cy1;
	cx1=(n1-1)/2.0;
    cy1=(m1-1)/2.0;

	cv::Mat tt1= cv::Mat(cv::Size(3,3), CV_32FC1); 
	cv::Mat tt2= cv::Mat(cv::Size(3,3), CV_32FC1); 
	cv::Mat tt3= cv::Mat(cv::Size(3,3), CV_32FC1); 
	cv::Mat tt4= cv::Mat(cv::Size(3,3), CV_32FC1); 

	tt1.at<float>(0,0)=cos(theta);
	tt1.at<float>(0,1)=sin(theta);
	tt1.at<float>(0,2)=0;
	tt1.at<float>(1,0)=-sin(theta);
	tt1.at<float>(1,1)=cos(theta);
	tt1.at<float>(1,2)=0;
	tt1.at<float>(2,0)=cx1-cx1*cos(theta)+cy1*sin(theta);
	tt1.at<float>(2,1)=cy1-cx1*sin(theta)-cy1*cos(theta);
	tt1.at<float>(2,2)=1;

	tt2.at<float>(0,0)=1;
	tt2.at<float>(0,1)=0;
	tt2.at<float>(0,2)=0;
	tt2.at<float>(1,0)=0;
	tt2.at<float>(1,1)=1;
	tt2.at<float>(1,2)=0;
	tt2.at<float>(2,0)=dx;
	tt2.at<float>(2,1)=dy;
	tt2.at<float>(2,2)=1;

	tt3.at<float>(0,0)=sx;
	tt3.at<float>(0,1)=0;
	tt3.at<float>(0,2)=0;
	tt3.at<float>(1,0)=0;
	tt3.at<float>(1,1)=sy;
	tt3.at<float>(1,2)=0;
	tt3.at<float>(2,0)=0;
	tt3.at<float>(2,1)=0;
	tt3.at<float>(2,2)=1;
		
	tt4.at<float>(0,0)=1;
	tt4.at<float>(0,1)=shy;
	tt4.at<float>(0,2)=0;
	tt4.at<float>(1,0)=shx;
	tt4.at<float>(1,1)=1;
	tt4.at<float>(1,2)=0;
	tt4.at<float>(2,0)=0;
	tt4.at<float>(2,1)=0;
	tt4.at<float>(2,2)=1;


	cv::Mat T= cv::Mat(cv::Size(3,3), CV_32FC1);

	T=tt1*tt2*tt3*tt4;
	cv::Mat TT=cv::Mat::zeros(2, 3, CV_32F);
	TT.at<float>(0,0)=T.at<float>(0,0);
	TT.at<float>(1,0)=T.at<float>(0,1);
	
	TT.at<float>(0,1)=T.at<float>(1,0);
	TT.at<float>(1,1)=T.at<float>(1,1);

	TT.at<float>(0,2)=T.at<float>(2,0);
	TT.at<float>(1,2)=T.at<float>(2,1);

	cv::Mat c = cv::Mat(a.rows,a.cols,CV_8U);
	
	imgaffine(a,c,TT);
	cv::namedWindow("test");
	cv::imshow("test",c);
	cv::waitKey();

	return 0;
}


void imgaffine(cv::Mat in,cv::Mat out,cv::Mat matrix)
{
	float* data_0=matrix.ptr<float>(0);
	float* data_1=matrix.ptr<float>(1);
	float a_00,a_01,a_02;
	float a_10,a_11,a_12;

	a_00=data_0[0];
	a_01=data_0[1];
	a_02=data_0[2];
	a_10=data_1[0];
	a_11=data_1[1];
	a_12=data_1[2];

	int width  =out.cols;
	int height =out.rows;
	for(int j=0;j<height;j++)
	{
		uchar* data_out = out.ptr<uchar>(j);
		for(int i=0;i<width;i++)
		{
			float y_in=(a_10*i - a_10*a_02 + a_00*a_12 - a_00*j)/(a_10*a_01 - a_00*a_11);
			float x_in=(a_11*i - a_01*j - a_11*a_02 + a_12*a_01)/(a_11*a_00 - a_01*a_10);
			if(x_in>in.cols || y_in>in.rows || x_in<0 || y_in<0)
				data_out[i]=0;
			else
			{
				//
				//不插值,直接替换
				/*
				int xx=(int)(x_in);
				int yy=(int)(y_in);
				uchar* zhizhen = in.ptr<uchar>(yy);
				data_out[i]=zhizhen[xx];
				*/
				/
				//双线型插值///
				
				int xx=(int)(x_in);
				int yy=(int)(y_in);
				int y1=yy+1;
				uchar* zhizhen  = in.ptr<uchar>(yy);
				if(yy<511)
				{	
					uchar* zhizhen1  = in.ptr<uchar>(y1);
					int aa=zhizhen[xx],
						bb=zhizhen[xx+1],
						cc=zhizhen1[xx],
						dd=zhizhen1[xx+1];
					float r1=aa+(bb-aa)*(x_in-xx);
					float r2=cc+(dd-cc)*(x_in-xx);
					float r3=r1+(r2-r1)*(y_in-yy);
					data_out[i]=(uchar)(r3);
				}
				else
					data_out[i]=zhizhen[xx];
			}
		}
	}

}
           

最近在往zedboard上面移植opencv的算法,一切都挺顺利的

只是有一个意料之外的问题

在arm上面做仿射变换时,得到的是一个错误的图像

刚开始怀疑是opencv库版本比较低的问题

可是换了高版本的库以后还是没用

这期间有一个比较蠢的错误

首先反思一下

就是设置opencv库的路径的时候,因为比较懒,没有复制文件路径,而是直接把2.3.1替换为2.4.8,结果没有注意文件夹名字的大小写问题

浪费了一天时间

昨天做linaro的图形界面

也是因为比较懒

没有重新制作文件系统

浪费了一天时间

到了今天

自己编写仿射变换的函数时

想偷懒,一直在师兄之前写的一个程序的基础上面改

改了一天没弄好

50+的代码

写了一天

结果刚才痛下决心自己重头写

一次通过!

事实证明,往往自己觉得最麻烦的方案才是最正确的方案

</pre><pre code_snippet_id="298776" snippet_file_name="blog_20140417_1_3152139" name="code" class="cpp"><pre code_snippet_id="298776" snippet_file_name="blog_20140417_1_3152139" name="code" class="cpp">
           

继续阅读