日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

OpenCV探索之路(八):重映射与仿射变换

發(fā)布時間:2025/3/20 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 OpenCV探索之路(八):重映射与仿射变换 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

重映射

重映射就是把一幅圖像中某個位置的像素放置到另一個圖片中指定位置的過程。

用一個數(shù)學(xué)公式來表示就是:

其中的 f 就是映射方式,也就說,像素點在另一個圖像中的位置是由 f 來計算的。

在OpenCV中,用的是remap函數(shù)實現(xiàn)重映射。

基本重映射

#include <iostream> #include <opencv2\opencv.hpp> #include <opencv2\imgproc\imgproc.hpp> #include <opencv2\highgui\highgui.hpp>using namespace cv; using namespace std;//基本重映射實驗int main() {Mat srcImage = imread("2.jpg");if (!srcImage.data){cout << "找不到這張圖片!" << endl;return -1;}imshow("Src Pic", srcImage);Mat dstImage, map_x, map_y;dstImage.create(srcImage.size(), srcImage.type());//創(chuàng)建和原圖一樣的效果圖map_x.create(srcImage.size(), CV_32FC1);map_y.create(srcImage.size(), CV_32FC1);//遍歷每一個像素點,改變map_x & map_y的值,實現(xiàn)翻轉(zhuǎn)180度for (int j = 0; j < srcImage.rows; j++){for (int i = 0; i < srcImage.cols; i++){map_x.at<float>(j, i) = static_cast<float>(i);map_y.at<float>(j, i) = static_cast<float>(srcImage.rows - j);}}//進行重映射操作remap(srcImage, dstImage, map_x, map_y, INTER_LINEAR, BORDER_CONSTANT, Scalar(0, 0, 0));imshow("重映射效果圖", dstImage); waitKey();return 0; }

map_x與map_y分別代表目標圖中的(x,y)點在原圖中的x坐標(由map_x提供)與y坐標(由map_y提供)。

運行效果,圖像翻轉(zhuǎn)了。

仿射變換

仿射變換指的是一個向量空間進行一次線性變換并接上一個平移,變換為另一個向量空間的過程。

圖像進行仿射變換后,有以下幾個特點:
二維圖形之間的相對位置關(guān)系保持不變,平行線依舊是平行線,且直線上的點的位置順序保持不變。

一個任意的仿射變換都可以表示為乘以一個矩陣(線性變換)接著再加上一個向量(平移)的形式。

三種常見形式:

  • 旋轉(zhuǎn),rotation(線性變換)
  • 平移,translation(向量加)
  • 縮放,scale(線性變換)

仿射變換本質(zhì)是一個2* 3的矩陣M乘上原圖的每個坐標,得到目標圖的對應(yīng)點坐標。2*3矩陣M中的2表示目標點坐標的x與y,3中的第三維是平移分量。因此需要做的就是找到矩陣M,OpenCV提供 getAffineTransform 求出仿射變換, getRotationMatrix2D 來獲得旋轉(zhuǎn)矩陣。

這里簡單說說仿射變換是怎么做到的。

現(xiàn)在有兩幅圖像(如下圖),圖像二是圖像一經(jīng)過放射變化得來的。那問題來了,我們怎么從這兩個圖像信息里挖掘出兩圖之間的映射關(guān)系?

很簡單,只要在圖像一種拿出三個點(1,2,3),圖像二也拿出對應(yīng)的三個點(1,2,3),就可以求出兩圖間的映射關(guān)系!

OpenCV通過兩個函數(shù)的組合使用來實現(xiàn)仿射變換:

  • 使用warpAffine來實現(xiàn)簡單重映射
  • 使用getRotationMatrix2D來獲得旋轉(zhuǎn)矩陣
#include<iostream> #include<opencv2/highgui/highgui.hpp> #include<opencv2/imgproc/imgproc.hpp> using namespace std; using namespace cv; //仿射變換實驗 int main() {Mat src = imread("lol9.jpg");Mat dst_warp, dst_warpRotateScale;Point2f srcPoints[3];//原圖中的三點 Point2f dstPoints[3];//目標圖中的三點 //第一種仿射變換的調(diào)用方式:三點法//三個點對的值,上面也說了,只要知道你想要變換后圖的三個點的坐標,就可以實現(xiàn)仿射變換 srcPoints[0] = Point2f(0, 0);srcPoints[1] = Point2f(0, src.rows - 1);srcPoints[2] = Point2f(src.cols - 1, 0);//映射后的三個坐標值dstPoints[0] = Point2f(0, src.rows*0.3);dstPoints[1] = Point2f(src.cols*0.25, src.rows*0.75);dstPoints[2] = Point2f(src.cols*0.75, src.rows*0.25);Mat M1 = getAffineTransform(srcPoints, dstPoints);//由三個點對計算變換矩陣 warpAffine(src, dst_warp, M1, src.size());//仿射變換 //第二種仿射變換的調(diào)用方式:直接指定角度和比例 //旋轉(zhuǎn)加縮放 Point2f center(src.cols / 2, src.rows / 2);//旋轉(zhuǎn)中心 double angle = 45;//逆時針旋轉(zhuǎn)45度 double scale = 0.5;//縮放比例 Mat M2 = getRotationMatrix2D(center, angle, scale);//計算旋轉(zhuǎn)加縮放的變換矩陣 warpAffine(dst_warp, dst_warpRotateScale, M2, src.size());//仿射變換 imshow("原始圖", src);imshow("仿射變換1", dst_warp);imshow("仿射變換2", dst_warpRotateScale);waitKey(0);return 0; }

兩種仿射變換的效果如下。

有沒有發(fā)現(xiàn)圖片進行仿射變換后的背景被填充為黑色了?其實這個背景色是可以調(diào)的,像這樣:

warpAffine(dst_warp, dst_warpRotateScale, M2, src.size(), 1, 0, Scalar(11,111, 211));//利用Scalar來填充不同顏色背景

然后背景色就變成這樣子了:

最后寫一個對圖片旋轉(zhuǎn)任何角度的代碼。

#include <opencv2/core/core.hpp> #include <opencv2/imgproc/imgproc.hpp> #include <opencv2/highgui/highgui.hpp> #include <iostream>using namespace cv; using namespace std;#define PIC_BEGIN_NUM 100 //這里定義你的起始圖片編號 #define ANGLE_START -45 //旋轉(zhuǎn)角度的開始 #define ANGLE_END 0 //旋轉(zhuǎn)角度的結(jié)束 #define ANGLE_STEP 2 //旋轉(zhuǎn)角度步長int main(int argc, char **argv) {//Read a single-channel imageconst char* filename = "lol9.jpg";Mat srcImg = imread(filename, 1);imshow("source", srcImg);Point center(srcImg.cols / 2, srcImg.rows / 2); //圖片中心為旋轉(zhuǎn)點char file[20];int count = PIC_BEGIN_NUM; Mat tmpimg; for (int tmp = ANGLE_START; tmp < ANGLE_END; tmp += ANGLE_STEP){Mat rotMatS = getRotationMatrix2D(center, tmp, 0.5); //圖片縮小到原來的0.5倍warpAffine(srcImg, tmpimg, rotMatS, srcImg.size(), 1, 0, Scalar(0, 0, 0));//填充黑色背景 sprintf(file, "%d.jpg", count++); //旋轉(zhuǎn)圖片以1.jpg 2.jpg 的名字格式保存imwrite(file, tmpimg);}waitKey(0);return 0; }

這里的代碼實現(xiàn)對圖片旋轉(zhuǎn)2度、4度...45度的功能,并將這些旋轉(zhuǎn)后的圖像保存先來。
然后文件夾下就出現(xiàn)旋轉(zhuǎn)好的圖片了!

轉(zhuǎn)載于:https://www.cnblogs.com/xieyulin/p/7060913.html

總結(jié)

以上是生活随笔為你收集整理的OpenCV探索之路(八):重映射与仿射变换的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。