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">


 

 
 
 

                
OpenCV中的仿射变换是一种对图像进行线性变换的方法,可以通过确定图像上的三个非共线点的位置,将原始图像变换为目标图像。首先,需要定义变换前的三个点和变换后的三个点,然后使用getAffineTransform函数计算仿射变换矩阵。最后,可以使用warpAffine函数应用仿射变换到原始图像上。 以下是一个使用OpenCV进行仿射变换的示例代码: ```cpp #include <opencv2/opencv.hpp> using namespace cv; int main(int argc, char** argv) { Mat src, dst_affine; Point2f srcPoints = Point2f(0, 0); srcPoints = Point2f(src.cols - 1, 0); srcPoints = Point2f(0, src.rows - 1); // 变换后的三个点坐标 dstPoints = Point2f(0, src.rows*0.5); dstPoints = Point2f(src.cols*0.8, src.rows*0.2); dstPoints = Point2f(src.cols*0.2, src.rows*0.9); // 计算仿射变换矩阵 Mat M = getAffineTransform(srcPoints, dstPoints); // 应用仿射变换到原始图像 warpAffine(src, dst_affine, M, src.size()); namedWindow("Affine Transformation"); imshow("Affine Transformation", dst_affine); waitKey(0); return 0; } ``` 此代码加载图像,定义了变换前的三个点和变换后的三个点的坐标,然后使用getAffineTransform函数计算仿射变换矩阵M。最后,使用warpAffine函数将变换应用到原始图像上,并显示结果图像。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [opencv——几何变换原理与实现](https://blog.csdn.net/qq_44386034/article/details/125637881)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值