实现openCV方法warpPerspective()
我试图从头开始实现openCV方法warpPerspective(),我编写了下面的代码,它可以处理y和x方向的偏移,但是,当我将单应矩阵从findHomography()传递给我创建的函数时,与warpPerspective()输出相比,它总是给出空白图像 我按照此定义查找像素的新位置:实现openCV方法warpPerspective(),opencv,transform,panoramas,image-stitching,360-panorama,Opencv,Transform,Panoramas,Image Stitching,360 Panorama,我试图从头开始实现openCV方法warpPerspective(),我编写了下面的代码,它可以处理y和x方向的偏移,但是,当我将单应矩阵从findHomography()传递给我创建的函数时,与warpPerspective()输出相比,它总是给出空白图像 我按照此定义查找像素的新位置: s*x'h1 h2 h3 x s*y'=h4 h5 h6*y s h7 h8 1 1 我的映射工作于简单的移位,如{1,0.5,-51,0,1,50,0,0,1} 但当矩阵类似于: [1.0340946,0
s*x'h1 h2 h3 x
s*y'=h4 h5 h6*y
s h7 h8 1 1
我的映射工作于简单的移位,如{1,0.5,-51,0,1,50,0,0,1}
但当矩阵类似于:
[1.0340946,0.032195676,-6.419126;
0.00302419, 1.0487343, -96.520393;
3.7013847e-06,0.00010837225,1]
输出如下:
我的实施:
-给定H和图像A,
-在A中找到像素的新位置并将其保存在TRANARRY中。其中数组的索引是A的线性化索引。
-将图像的像素重新映射到变换中
Mat transform(Mat A, Mat H)
{
// allocate array of all locations
int Numrows = A.rows;
int Numcols = A.cols;
int channels = A.channels();
cout << "rows " << Numrows << "col " << Numcols << "channels " << channels <<endl;
int size = Numrows*Numcols;
int MaxX,MaxY = -1000;
int MinX,MinY = 1000;
int *TransArry = (int *)malloc(sizeof(int)*size);
int Idx;
int homeX=Idx % Numcols;
int homeY=Idx / Numcols;
cout << H << endl;
waitKey();
for (Idx=0; Idx < size; ++Idx ){
homeX=Idx % Numcols;
homeY=Idx / Numcols;
float x = (H.at<float>(0,0) * (homeX)) +( H.at<float>(0,1) * (homeY)) + ( H.at<float>(0,2) * 1) ;
float y = (H.at<float>(1,0) * (homeX)) +( H.at<float>(1,1) * (homeY)) + ( H.at<float>(1,2) * 1) ;
float s = (H.at<float>(2,0) * (homeX)) +( H.at<float>(2,1) * (homeY)) + ( H.at<float>(2,2) * 1) ;
cout << " x = " << x << " y= " << y << " s= " << s;
x = (x/s);
y = y/s;
// for the first col in TransMatrix
if (homeX ==0){
if (x > MaxX) MaxX = x;
if (x < MinX) MinX = x;
}
//for thee first row in TransMatrix
if (homeY ==0){
if (y > MaxY) MaxY = y;
if (y < MinY) MinY = y;
}
if((y)>=A.rows || (y)<0 || (x)>=A.cols || (x)<0){
TransArry[Idx] = -1;
cout << "x= " << x << "y= "<< y << endl;
}else{
TransArry[Idx] = (y * Numcols + x);
}
//cout << Numcols << endl;
cout << "New index of " << Idx << "is " << TransArry[Idx] << endl;
}
Mat tranImg ;
A.copyTo(tranImg);
tranImg = tranImg - tranImg;
cout << "Rows" << tranImg.rows << "cols" << tranImg.cols << "cha" << A.channels() << endl;
waitKey();
// Remap Image
for (Idx=0; Idx < size; Idx ++ ){
homeX=Idx % Numcols;
homeY=Idx / Numcols;
//tranImg.at<uchar>(homeY, homeX) =0;
if(TransArry[Idx] != -1){
//cout << "Index " << Idx << "Passed " << endl;
int newhomeX=TransArry[Idx] % Numcols; // Col ID
int newhomeY=TransArry[Idx] / Numcols; // Row ID
cout << "Index is " << Idx << endl;
cout << "HomeX is " << homeX << " and HomeY is " << homeY << endl;
cout << "New Index is " << TransArry[Idx] << endl;
cout << "New HomeX is " << newhomeX << " and New HomeY is " << newhomeY << endl;
cout << "*****************************************"<< endl;
// if (!(Idx%100)) sleep(20);
tranImg.at<uchar>(newhomeY, (newhomeX*channels)) = A.at<uchar>(homeY, homeX*channels);
if(channels>1)
tranImg.at<uchar>(newhomeY, newhomeX*channels+1) = A.at<uchar>(homeY, homeX*channels+1);
if(channels>2)
tranImg.at<uchar>(newhomeY, newhomeX*channels+2) = A.at<uchar>(homeY, homeX*channels+2);
// if (!(Idx%100)){
// imshow("inside", tranImg);
// waitKey(1);
// }
}
}
//cout << tranImg << endl;
return tranImg;
}
Mat变换(Mat A,Mat H)
{
//分配所有位置的数组
int Numrows=A.行;
int Numcols=A.cols;
int channels=A.channels();
看我的答案,它应该能回答你的两个问题。这个答案仍然使用wartprospective()
,但它提供了关于如何计算单应性扭曲图像超出图像边界多远的完整见解,因此你可以在图像的每一侧进行适当的填充
至于手动执行warpPerspective()
,只需将所有图像坐标放入一个线性化的齐次数组中,乘以单应矩阵,然后除以最后一个坐标返回笛卡尔坐标。remap()的语法
可能会让人困惑,因此您可以参考我的答案了解如何使用它。此答案显示了手动转换和插值,它应该会给您(至少)与warpPerspective()相同的结果
我发现了问题。您使用的坐标是浮点值而不是整数。将x和y类型转换为整数和下限值x=下限(x/s)和y=下限(y/s).谢谢你的详细回答,我尝试了一个解决方案,但没有得到旋转的图像。我是否应该将我的代码发布到另一个问题?因为我在处理矩阵元素和尝试将其转换为c数组时遇到问题。@KaramAboGhalieh我认为它仍然适合这个问题的范围。好的,你应该编辑你原来的帖子d包括代码和当前问题(但我建议不要删除您当前的任何帖子)。编辑您的帖子也会使其出现在问题队列中,因此您可能会得到更多的回复。另外,请查看我的GitHub repo,这可能会有所帮助。我的实现在x或y移位时运行良好,但无法处理完整的Hmatrix@KaramAboGhalieh上面的缩进非常混乱,代码很难阅读把它放大一点,这样会更容易发现任何问题。你能给出输入和当前输出的例子吗?你说“不能处理完整的H矩阵”是什么意思?很抱歉,现在呢?我所说的完整矩阵是什么意思,比如{0.97744,-0.014668,1.75,-0.00308,0.96445,91.30,-4.80865,-7.4539,1};我能处理这个问题例如{1,0.5,-51,0,1,50,0,0,1}矩阵,但不是之前的矩阵。