由於某些原因,每當我使用OpenCV的warpPerspective()函數時,最終變形的圖像並不包含原始圖像中的所有內容。圖像的左側部分似乎被切斷。我認爲發生這種情況的原因是因爲warpPerspective()在畫布的最左側位置創建了變形圖像。有沒有辦法解決這個問題?謝謝OpenCV warpperspective
回答
warpPerspective()正常工作。不需要重寫它。 您可能使用不正確。
請記住以下提示:
- (0,0)的像素是不是在市中心,而是左上角。所以,如果你放大圖像x2,你將失去較低和正確的部分,而不是邊界(就像在matlab中)。
- 如果兩次變形圖像,最好將變換相乘並激活一次函數。
- 我認爲它只適用於char/int矩陣,而不是float/double。
- 當您進行轉換時,首先應用縮放/傾斜/旋轉/透視,最後進行轉換。因此,如果部分圖像丟失,只需更改矩陣中的換位(最後一列的兩行)。
祕密分爲兩部分:變換矩陣(單應性)和由此產生的圖像大小。
通過使用getPerspectiveTransform()計算正確的轉換。從原始圖像中取4個點,計算它們在目的地的正確位置,將它們按照相同的順序放入兩個向量中,並使用它們來計算透視變換矩陣。
確保目標圖像大小(warpPerspective()的第三個參數)正是您想要的。將其定義爲Size(myWidth,myHeight)。
問題發生的原因是單應圖將部分圖像映射到圖像區域外的負x,y值,因此無法繪製。 我們希望做的是抵消一些像素的扭曲輸出,將整個變形圖像「分流」爲正座標(因此在圖像區域內)。
可以使用矩陣乘法來組合同形(這就是爲什麼它們如此強大)。如果A和B是單應性,那麼AB代表首先應用B的單應性,然後A.因此,我們需要做的是抵消輸出是爲某個偏移量的平移創建單應矩陣,並且然後預乘上我們原來的單應性矩陣
甲2D單應性矩陣是這樣的:
[R11,R12,T1]
[R21,R22,T2]
[ P , P , 1]
其中R表示旋轉矩陣,T表示翻譯,和P表示的立體翹曲。 所以純粹的平移單應是這樣的:
[ 1 , 0 , x_offset]
[ 0 , 1 , y_offset]
[ 0 , 0 , 1 ]
所以只要你的預乘單應通過類似上述矩陣,並且您的輸出圖像將被抵消。
(確保你使用的矩陣乘法,而不是元素方式乘法!)
似乎x_offset和y_offset應該乘以-1。我不知道爲什麼。我嘗試了正面,並且將圖像朝相反的方向移動。 – Steve 2017-03-12 03:48:21
我做了一個方法...... 這是工作。
perspectiveTransform(obj_corners,scene_corners,H);
int maxCols(0),maxRows(0);
for(int i=0;i<scene_corners.size();i++)
{
if(maxRows < scene_corners.at(i).y)
maxRows = scene_corners.at(i).y;
if(maxCols < scene_corners.at(i).x)
maxCols = scene_corners.at(i).x;
}
我只是覺得最大的X點和Y點的分別,把它放在
warpPerspective(tmp, transformedImage, homography, Size(maxCols, maxRows));
嘗試以下homography_warp
。
void homography_warp(const cv::Mat& src, const cv::Mat& H, cv::Mat& dst);
src
是源圖像。
H
是你的單性生活。
dst
是扭曲的圖像。
homography_warp
調整單應爲他的答案通過https://stackoverflow.com/users/1060066/matt-freeman描述https://stackoverflow.com/a/8229116/15485
// Convert a vector of non-homogeneous 2D points to a vector of homogenehous 2D points.
void to_homogeneous(const std::vector<cv::Point2f>& non_homogeneous, std::vector<cv::Point3f>& homogeneous)
{
homogeneous.resize(non_homogeneous.size());
for (size_t i = 0; i < non_homogeneous.size(); i++) {
homogeneous[i].x = non_homogeneous[i].x;
homogeneous[i].y = non_homogeneous[i].y;
homogeneous[i].z = 1.0;
}
}
// Convert a vector of homogeneous 2D points to a vector of non-homogenehous 2D points.
void from_homogeneous(const std::vector<cv::Point3f>& homogeneous, std::vector<cv::Point2f>& non_homogeneous)
{
non_homogeneous.resize(homogeneous.size());
for (size_t i = 0; i < non_homogeneous.size(); i++) {
non_homogeneous[i].x = homogeneous[i].x/homogeneous[i].z;
non_homogeneous[i].y = homogeneous[i].y/homogeneous[i].z;
}
}
// Transform a vector of 2D non-homogeneous points via an homography.
std::vector<cv::Point2f> transform_via_homography(const std::vector<cv::Point2f>& points, const cv::Matx33f& homography)
{
std::vector<cv::Point3f> ph;
to_homogeneous(points, ph);
for (size_t i = 0; i < ph.size(); i++) {
ph[i] = homography*ph[i];
}
std::vector<cv::Point2f> r;
from_homogeneous(ph, r);
return r;
}
// Find the bounding box of a vector of 2D non-homogeneous points.
cv::Rect_<float> bounding_box(const std::vector<cv::Point2f>& p)
{
cv::Rect_<float> r;
float x_min = std::min_element(p.begin(), p.end(), [](const cv::Point2f& lhs, const cv::Point2f& rhs) {return lhs.x < rhs.x; })->x;
float x_max = std::max_element(p.begin(), p.end(), [](const cv::Point2f& lhs, const cv::Point2f& rhs) {return lhs.x < rhs.x; })->x;
float y_min = std::min_element(p.begin(), p.end(), [](const cv::Point2f& lhs, const cv::Point2f& rhs) {return lhs.y < rhs.y; })->y;
float y_max = std::max_element(p.begin(), p.end(), [](const cv::Point2f& lhs, const cv::Point2f& rhs) {return lhs.y < rhs.y; })->y;
return cv::Rect_<float>(x_min, y_min, x_max - x_min, y_max - y_min);
}
// Warp the image src into the image dst through the homography H.
// The resulting dst image contains the entire warped image, this
// behaviour is the same of Octave's imperspectivewarp (in the 'image'
// package) behaviour when the argument bbox is equal to 'loose'.
// See http://octave.sourceforge.net/image/function/imperspectivewarp.html
void homography_warp(const cv::Mat& src, const cv::Mat& H, cv::Mat& dst)
{
std::vector<cv::Point2f> corners;
corners.push_back(cv::Point2f(0, 0));
corners.push_back(cv::Point2f(src.cols, 0));
corners.push_back(cv::Point2f(0, src.rows));
corners.push_back(cv::Point2f(src.cols, src.rows));
std::vector<cv::Point2f> projected = transform_via_homography(corners, H);
cv::Rect_<float> bb = bounding_box(projected);
cv::Mat_<double> translation = (cv::Mat_<double>(3, 3) << 1, 0, -bb.tl().x, 0, 1, -bb.tl().y, 0, 0, 1);
cv::warpPerspective(src, dst, translation*H, bb.size());
}
這是我的解決方案
因爲在 「warpPerspective()」 第三個參數是變換矩陣,
我們可以創建一個變換矩陣,它首先向後移動圖像,然後旋轉圖像,最後向前移動圖像。
在我的情況下,我有一個高度爲160像素,寬度爲160像素的圖像。 欲繞[80,80]的圖像,而不是圍繞[0,0]
第一,使圖像向後移動(這意味着T1)
然後旋轉圖像(這意味着R)
終於使圖像向前移動(這意味着T2)
void rotateImage(Mat &src_img,int degree)
{
float radian=(degree/180.0)*M_PI;
Mat R(3,3,CV_32FC1,Scalar(0));
R.at<float>(0,0)=cos(radian);R.at<float>(0,1)=-sin(radian);
R.at<float>(1,0)=sin(radian);R.at<float>(1,1)=cos(radian);
R.at<float>(2,2)=1;
Mat T1(3,3,CV_32FC1,Scalar(0));
T1.at<float>(0,2)=-80;
T1.at<float>(1,2)=-80;
T1.at<float>(0,0)=1;
T1.at<float>(1,1)=1;
T1.at<float>(2,2)=1;
Mat T2(3,3,CV_32FC1,Scalar(0));
T2.at<float>(0,2)=80;
T2.at<float>(1,2)=80;
T2.at<float>(0,0)=1;
T2.at<float>(1,1)=1;
T2.at<float>(2,2)=1;
std::cerr<<T1<<std::endl;
std::cerr<<R<<std::endl;
std::cerr<<T2<<std::endl;
std::cerr<<T2*R*T1<<"\n"<<std::endl;
cv::warpPerspective(src_img, src_img, T2*R*T1, src_img.size(), cv::INTER_LINEAR);
}
- 1. OpenCV的getPerspectiveTransform和warpPerspective的Java
- 2. OpenCV的warpPerspective參數計算
- 3. OpenCV:瞭解warpPerspective /透視變換
- 4. 在OpenCV 2.x中指定warpPerspective()函數的原點
- 5. 如何在應用warpperspective(opencv)之後發現座標(0,0)?
- 6. 圖像使用opencv變形
- 7. 如何在openCV中變形文本?
- 8. 圖像拼接神器[OpenCV Python]
- 9. 計算的OpenCV的findHomography目標點
- 10. OpenCV Center同形異形
- 11. Homographie Opencv適用於Opengl
- 12. 蟒蛇opencv全景黑線
- 13. Opencv調整一個針跡
- 14. OpenCV warp問題與透明圖像
- 15. 從視頻穩定程序將C/++ OpenCV程序更改爲CUDA
- 16. 從python使用Opencv Cuda功能
- 17. java.lang.NoClassDefFoundError:org/opencv/core/Core - Java Servlet + OpenCV
- 18. 使用Python用的OpenCV實現圖像拼接
- 19. 幫助使用OpenCV warp查看和透視變換
- 20. 使用opencv讀取xml文件type_id opencv-image使用opencv
- 21. OPENCV Thresholding
- 22. openCV cvContourArea
- 23. OpenCV getMinFilter_GPU
- 24. Mat.Depth()Opencv
- 25. OpenCV createTrackbar
- 26. Haartraining opencv
- 27. OpenCV progressBar
- 28. Python - 從旋轉角度對OpenCV進行透視變換
- 29. Python的OpenCV的錯誤
- 30. 在opencv中拼接2張圖片
'墊TMP; cv :: resize(imageList [image1],tmp,Size(),scaleFactor,scaleFactor); warpPerspective(tmp,transformedImage,Homography,Size(2 * tmp.cols,2 * tmp.rows));' – Hien 2011-05-23 02:38:47
我不知道如何在評論>。<中格式化。無論如何,這是我目前使用warpPerspective的代碼片段。自從我使用高分辨率圖像以來,單應從2幅圖像的調整版本中提取。你能讓我知道我做錯了什麼嗎?謝謝 – Hien 2011-05-23 02:42:10