Opencv——幾何空間變換(仿射變換和投影變換)

幾何空間變換

    • 【1】幾何變換(空間變換)簡述
    • 【2】變換矩陣知識簡述
      • 齊次坐標的概念
      • 幾何運算矩陣
    • 【3】圖像的仿射變換
      • 1、平移變換
      • 2、比例縮放
      • 3、旋轉
      • 4、對稱變換(不做展示)
        • 1、關于X軸變換
        • 2、關于Y軸變換
        • 3、關于直線Y=X變換
        • 4、關于直線Y=-X變換
      • 5、錯切變換
      • 6、復合變換
    • 【4】圖像的投影變換
    • 【5】應用
    • 【6】Opencv自帶的變換函數:
      • Opencv中仿射變換的函數:warpAffine()函數
      • Opencv中計算二維旋轉變換矩陣: getRotationMatrix2D()函數

【1】幾何變換(空間變換)簡述

圖像的幾何變換,又稱空間變換,是圖形處理的一個方面,是各種圖形處理算法的基礎。它將一幅圖像中的坐標位置映射到另一幅圖像中的新坐標位置,其實質是改變像素的空間位置,估算新空間位置上的像素值。
幾何變換算法一般包括空間變換運算和插值算法。
集中常見的變換

【2】變換矩陣知識簡述

齊次坐標的概念

圖像一般是二維的,坐標形式為(x,y)。
這里我們將其擴展為3維形式的齊次坐標。形式如下:
坐標形式
第三個參數是尺度參數,控制尺度縮放。(1的時候表示尺度不變)
齊次坐標使用n+1維,來表示n維的坐標。它的優點如下所示:

●統一坐標的加法運算和乘法運算, 運算時提高效率。
●表示無窮遠的點。 當z=0的時候,表示無窮遠的點。
( x,y,z) ----->( x/z, y/z) ;齊次坐標和二維坐標的換算
如,(2,2,1),(4,4,2 )表示同樣的點。

幾何運算矩陣

運算矩陣
最左邊是變換后的齊次坐標,中間的是原圖點的其次坐標,最右邊是變換矩陣,有9個參數,分為4個子矩陣,每個子矩陣具有特殊意義。
T1:比例、旋轉、對稱、錯切
T2:平移
T3:投影
T4:整體縮放(通常我們通過T1實現縮放,所以這里通常為1)
所謂的仿射變換其實就是通過T1、T2進行變換。
所謂的投影變換就是在仿射變換上多用到了T3。
這里我們忽略T4。

【3】圖像的仿射變換

為了能夠直觀地了解參數對于變換的各種影響,我編寫了一個程序,通過滑動條來控制參數,同時顯示參數改變后的圖像。
這里的參數我都是設的正的,你把滑動條從正最大移到0就相當于是逆操作了。
代碼如下:

#include <opencv2/opencv.hpp>
#include <iostream>
#include "windows.h"
#include <stdio.h>
#define WINDOW_NAME "【程序窗口】"			//為窗口標題定義的宏using namespace cv;
using namespace std;//*--------------------------【全局變量聲明】-------------------------------------*///*--------------------------【T1】-------------------------------------*/
int g_nValueA = 100;
int g_nValueB = 0;
int g_nValueC = 0;
int g_nValueD = 100;
//*--------------------------【T2】-------------------------------------*/
int g_nValueL = 50;
int g_nValueM = 50;
//*--------------------------【T3】-------------------------------------*/
int g_nValueP = 0;
int g_nValueQ = 0;
//*--------------------------【T4】-------------------------------------*/
int I_max = 400;
int g_nValueS = 100;
int theta = 0;
int change_switch = 0;
int center_x = I_max / 2;
int center_y = I_max / 2;
Mat g_srcImage,g_dstImage;void on_change(int, void*);	//回調函數int main()
{SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_GREEN);		//字體為綠色//原圖,仿射變換后的圖,旋轉變換后的圖g_srcImage = Mat::zeros(I_max, I_max, CV_8UC1);g_dstImage = Mat::zeros(I_max, I_max, CV_8UC1);for (int i = I_max/2;i < I_max/2+50;i++)	//行循環{for (int j = I_max / 2;j < I_max / 2 + 50;j++)	//列循環{//-------【開始處理每個像素】---------------g_srcImage.at<uchar>(i, j) = 255;//-------【處理結束】---------------}}namedWindow(WINDOW_NAME, WINDOW_NORMAL);//WINDOW_NORMAL允許用戶自由伸縮窗口imshow("原圖", g_srcImage);//【4】創建滑動條來控制閾值createTrackbar("a", WINDOW_NAME, &g_nValueA,150, on_change);createTrackbar("b", WINDOW_NAME, &g_nValueB, 150, on_change);createTrackbar("c", WINDOW_NAME, &g_nValueC, 150, on_change);createTrackbar("d", WINDOW_NAME, &g_nValueD, 150, on_change);createTrackbar("l", WINDOW_NAME, &g_nValueL, 150, on_change);createTrackbar("m", WINDOW_NAME, &g_nValueM, 150, on_change);createTrackbar("p", WINDOW_NAME, &g_nValueP, 150, on_change);createTrackbar("q", WINDOW_NAME, &g_nValueQ, 150, on_change);createTrackbar("s", WINDOW_NAME, &g_nValueS, 150, on_change);createTrackbar("角度", WINDOW_NAME, &theta, 360, on_change);createTrackbar("switch", WINDOW_NAME, &change_switch, 1, on_change);on_change(0,0);	//初始化回調函數//【7】輪詢等待用戶按鍵,如果ESC鍵按下則退出程序while (1){if (waitKey(10) == 27) break;		//按下Esc 退出}return 0;}
//*--------------------------【on_Threshold 函數】-------------------------------------*/
void on_change(int, void*)
{g_dstImage = Mat::zeros(I_max, I_max, CV_8UC1);float a = g_nValueA * 0.01;float b = g_nValueB * 0.01;float c = g_nValueC * 0.01;float d = g_nValueD * 0.01;int l = g_nValueL;int m = g_nValueM;float p = g_nValueP * 0.0005;float q = g_nValueQ * 0.0005;float s = g_nValueS * 0.01;int x_change, y_change;//將參數進行處理//計算坐標if (change_switch == 0){for (int x = I_max / 2;x < I_max / 2 + 50;x++)	//行循環{for (int y = I_max / 2;y < I_max / 2 + 50;y++)	//列循環{x_change = (a * x + c * y + l) / (p * x + q * y + 1);y_change = (b * x + d * y + m) / (p * x + q * y + 1);//限幅 if (x_change >= I_max) x_change = I_max - 1;else if (x_change <= 0) x_change = 0;else{}if (y_change >= I_max) y_change = I_max - 1;else if (y_change <= 0) y_change = 0;else{}g_dstImage.at<uchar>(x_change, y_change) = 255;}}}else{a = cos(theta);b = sin(theta);c = -1 * sin(theta);d = cos(theta);for (int x = I_max / 2;x < I_max / 2 + 50;x++)	//行循環{for (int y = I_max / 2;y < I_max / 2 + 50;y++)	//列循環{x_change = (x - center_x) * cos(theta) - (y - center_y) * sin(theta) + center_x;y_change = (x - center_x) * sin(theta) + (y - center_y) * cos(theta)+ center_y;//限幅 if (x_change >= I_max) x_change = I_max - 1;else if (x_change <= 0) x_change = 0;else{}if (y_change >= I_max) y_change = I_max - 1;else if (y_change <= 0) y_change = 0;else{}g_dstImage.at<uchar>(x_change, y_change) = 255;}}}//更新效果圖imshow("效果圖", g_dstImage);
}

原圖如下:
原圖
接下來看具體變換:

1、平移變換

平移變換
效果展示:
平移

2、比例縮放

比例縮放
比例縮放
效果展示:
縮放

3、旋轉

在這里插入圖片描述
在這里插入圖片描述
這里的旋轉是以原點為中心點的,當我們以(center_x,center_y)為中點,則需要修改公式為:

X’=(X-center_x)*cos(theta)-(Y-center_y)*sin(theta) + center_x;
Y’=(X-center_x)*sin(theta)+(Y-center_y)*cos(theta) +center_y ;

效果展示:
旋轉

4、對稱變換(不做展示)

1、關于X軸變換

1

2、關于Y軸變換

2

3、關于直線Y=X變換

3

4、關于直線Y=-X變換

4

5、錯切變換

1
2
效果展示:
錯切

6、復合變換

復合變換

【4】圖像的投影變換

投影變換
點共線特性:原本是一條直線,變換后還是一條直線
變換
效果展示:
投影變換

【5】應用

矯正圖像
由原理可知,變換的本質就是通過對應點組的坐標來求解方程。一個變換是否理想,在公式不做調整的情況下就要看對應點的選擇。
這里我們一般選擇圖像的特征點。這些知識會在以后展開講,哲理不做過多擴展。(像上面的二維碼變換,我們選取的特征點考慮那三個定位點,當然還要再找一個特征點。以后掌握了這方面知識再補充。)

【6】Opencv自帶的變換函數:

Opencv中仿射變換的函數:warpAffine()函數

公式依據:
公式依據

C++: void warpAffine (InputArray src, OutputArray dst, InputArray M, Size
dsize, int flags=INTER_LINEAR,intborderMode=BORDER_CONSTANT, const
Scalar& borderValue=Scalar() )
第一個參數,InputArray 類型的src,輸入圖像,即源圖像,填Mat類的對
象即可。
第二個參數,OutputArray 類型的dst, 函數調用后的運算結果存在這里,
需和源圖片有一樣的尺寸和類型。
第三個參數,InputArray 類型的M,2x3 的變換矩陣。
第四個參數,Size 類型的dsize,表示輸出圖像的尺寸。
第五個參數,int 類型的flags, 插值方法的標識符。此參數有默認值
INTER_ LINEAR(線性插值),可選的插值方式如下圖所示。
在這里插入圖片描述
第六個參數,int類型的borderMode,邊界像素模式,默認值為
BORDER CONSTANT。
第七個參數,const Scalar&類型的borderValue, 在恒定的邊界情況下取的
值,默認值為Scalar(), 即0。

Opencv中計算二維旋轉變換矩陣: getRotationMatrix2D()函數

C++: Mat getRotationMatrix2D (Point2fcenter, double angle, double scale)
第一個參數,Point2f 類型的center,表示源圖像的旋轉中心。
第二個參數,double類型的angle,旋轉角度。角度為正值表示向逆時針旋轉(坐標原點是左上角)。
第三個參數,double 類型的scale,縮放系數。
計算公式

int main()
{SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_GREEN);		//字體為綠色//【1】參數準備//定義兩組點,代表兩個三角形Point2f srcTriangle[3];Point2f dstTriangle[3];//定義Mat變量(變換矩陣)Mat rotMat(2, 3, CV_32FC1);	//CV_32FC1代表多少?Mat warpMat(2, 3, CV_32FC1);	//CV_32FC1代表多少?Mat srcImage, dstImage_warp, dstImage_warp_roate;//原圖,仿射變換后的圖,旋轉變換后的圖srcImage = imread("D:\\opencv_picture_test\\形態學操作\\黑白.jpg");//判斷圖像是否加載成功if (srcImage.empty()){cout << "圖像加載失敗!" << endl;return -1;}elsecout << "圖像加載成功!" << endl << endl;dstImage_warp = Mat::zeros(srcImage.rows, srcImage.cols, srcImage.type());		//轉換圖和原圖像類型一樣大小一樣//【2】利用三組對應點來計算參數srcTriangle[0] = Point2f(0, 0);		//這些選擇自己決定srcTriangle[1] = Point2f(0, 0);srcTriangle[2] = Point2f(0, 0);dstTriangle[0] = Point2f(0, 0);dstTriangle[1] = Point2f(0, 0);dstTriangle[2] = Point2f(0, 0);//【3】求得仿射變換參數warpMat = getAffineTransform(srcTriangle, dstTriangle);		//利用對應點求得6個參數//【4】對原圖進行仿射變換warpAffine(srcImage,dstImage_warp,warpMat,dstImage_warp.size());//【5】獲取旋轉信息Point center = Point(dstImage_warp.cols / 2, dstImage_warp.rows / 2);	//中心點double angle = -30.0;			//順時針30度double scale =0.8;//【6】通過上面的旋轉細節信息求得旋轉矩陣rotMat = getRotationMatrix2D(center, angle,scale);//【7】對縮放后的圖像進行旋轉warpAffine(dstImage_warp,dstImage_warp_roate, rotMat,dstImage_warp.size());//【8】顯示結果namedWindow("原圖像", WINDOW_NORMAL);     //定義窗口顯示屬性imshow("原圖像", srcImage);namedWindow("縮放圖", WINDOW_NORMAL);     //定義窗口顯示屬性imshow("縮放圖", dstImage_warp);namedWindow("縮放旋轉圖", WINDOW_NORMAL);     //定義窗口顯示屬性imshow("縮放旋轉圖", dstImage_warp_roate);//創建三個窗口waitKey(0);return 0;
}

效果:
效果
PPT是盜用的我們李竹老師的,嘿嘿。
圖像

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/378661.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/378661.shtml
英文地址,請注明出處:http://en.pswp.cn/news/378661.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

用于主題檢測的臨時日志(e1784e6f-037e-45de-bad1-8bbc239818ee - 3bfe001a-32de-4114-a6b4-4005b770f6d7)...

這是一個未刪除的臨時日志。請手動刪除它。(578392f7-2207-4b01-b36d-c483f0699988 - 3bfe001a-32de-4114-a6b4-4005b770f6d7)轉載于:https://www.cnblogs.com/Fly-sky/archive/2011/03/03/1969850.html

probuffer java_Protocol Buffer的使用

Probotbuf簡介在網絡通信和通用數據交換等應用場景中經常使用的技術是 JSON 或 XML&#xff0c;這兩種技術常被用于數據的結構化呈現和序列化。我們可以從兩個方面來看JSON 和 XML與protobuf的異同&#xff1a;一個是數據結構化&#xff0c;一個是數據序列化。這里的數據結構化…

根據DbSchema生成代碼2

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ComponentModel; using System.Threading; using System.IO; using Rocky;namespace Rocky.CodeBuilder {public class DbBuilder : Disposable{#region 字段public even…

22-隨機抽樣一致算法RANSAC

隨機抽樣一致算法(Random sample consensus&#xff0c;RANSAC) 看似復雜&#xff0c;其基本思想就是&#xff1a;隨機選取倆點&#xff0c;然后連接&#xff0c;給定一個容忍范圍&#xff0c;在這個范圍內的點越多越好&#xff0c;然后不斷的迭代進行找兩點之間容忍范圍內點最…

treeset比較器_Java TreeSet比較器()方法與示例

treeset比較器TreeSet類的compare()方法 (TreeSet Class comparator() method) comparator() method is available in java.util package. 比較器()方法在java.util包中可用。 comparator() method is used to get the Comparator object based on customizing order the eleme…

智能車復工日記【1】——菜單索引回顧

博主聯系方式: QQ:1540984562 QQ交流群:892023501 群里會有往屆的smarters和電賽選手,群里也會不時分享一些有用的資料,有問題可以在群里多問問。 菜單回顧 1、系列文章解析結構元素菜單圖示菜單缺點:1、系列文章 【智能車Code review】—曲率計算、最小二乘法擬合 【智能…

[轉載]Oracle 11g R1下的自動內存經管(2)

AMM調整 除現有的用于內存經管的V$視圖外&#xff0c;Oracle 11g還新添加了下面4個視圖用于自動內存經管&#xff1a; ? ◆V$MEMORY_CURRENT_RESIZE_OPS ? ◆V$MEMORY_DYNAMIC_COMPONENTS ? ◆V$MEMORY_RESIZE_OPS ? ◆V$MEMORY_TARGET_ADVICE 轉載于:https://www.cnblogs.…

23-背景建模

幀差法 由于場景中的目標在運動&#xff0c;目標的影像在不同圖像幀中的位置不同。該類算法對時間上連續的兩幀圖像進行差分運算&#xff0c;不同幀對應的像素點相減&#xff0c;判斷灰度差的絕對值&#xff0c;當絕對值超過一定閾值時&#xff0c;即可判斷為運動目標&#xf…

DB2 9 運用開辟(733 考試)認證指南,第 3 部門: XML 數據獨霸(4)

議決運用順序存儲和檢索 XMLXML 編碼字符編碼在汗青上&#xff0c;術語 字符集、字符編碼 和 碼頁 都有雷同的意義&#xff1a;一個字符集和一個二進制碼集&#xff0c;其中每個碼示意一個字符。&#xff08;碼頁是來自 IBM 的一個術語&#xff0c;示意一個大型主機或 IBM PC 上…

system.setin_Java System類setIn()方法及示例

system.setin系統類setIn()方法 (System class setIn() method) setIn() method is available in java.lang package. setIn()方法在java.lang包中可用。 setIn() method is used to assign again the standard input stream. setIn()方法用于再次分配標準輸入流。 setIn() met…

Opencv——霍夫變換以及遇到的一些問題

目錄問題1 &#xff1a;顏色空間轉換函數參數問題&#xff1a;CV_BGR2GRAY vs CV_GRAY2BGR問題2&#xff1a;cvRound()、cvFloor()、cvCeil()函數用法霍夫變換的含義標準霍夫直線變換霍夫線變換函數參數講解累計概率霍夫變換霍夫變換圓變換原理和算法步驟&#xff1a;霍夫圓變換…

java ssm如何上傳圖片_ssm整合-圖片上傳功能(轉)

本文介紹 ssm (SpringSpringMVCMybatis)實現上傳功能。以一個添加用戶的案例介紹(主要是將上傳文件)。一、需求介紹我們要實現添加用戶的時候上傳圖片(其實任何文件都可以)。文件名&#xff1a;以 博客名日期的年月日時分秒毫秒形式命名如 言曌博客2017082516403213.png路徑&am…

宏定義和內聯函數區別

內聯函數是代碼被插入到調用者代碼處的函數。如同 #define 宏&#xff0c;內聯函數通過避免被調用的開銷來提高執行效率&#xff0c;尤其是它能夠通過調用&#xff08;“過程化集成”&#xff09;被編譯器優化。 宏定義不檢查函數參數&#xff0c;返回值什么的&#xff0c;只是…

24-光流估計

光流是空間運動物體在觀測成像平面上的像素運動的“瞬間速度”&#xff0c;根據各個像素點的速度矢量特征&#xff0c;可以對圖像進行動態分析&#xff0c;例如目標跟蹤 亮度恒定&#xff1a;同一點隨著時間的變化&#xff0c;其亮度不會發生改變 小運動&#xff1a;隨著時間的…

java公平索非公平鎖_java中的非公平鎖不怕有的線程一直得不到執行嗎

首先來看公平鎖和非公平鎖&#xff0c;我們默認使用的鎖是非公平鎖&#xff0c;只有當我們顯示設置為公平鎖的情況下&#xff0c;才會使用公平鎖&#xff0c;下面我們簡單看一下公平鎖的源碼&#xff0c;如果等待隊列中沒有節點在等待&#xff0c;則占有鎖&#xff0c;如果已經…

mybatis.net - 5 嵌入資源與引用資源

在SqlMap.config文件中可以有兩種方式引入外部的文件。 一種是通過資源的方式&#xff0c;在文件中表現為 resource&#xff0c;就是引用外部的文件&#xff0c;這里需要保證文件的路徑正確。 <sqlMaps><sqlMap resource"Maps/ProductMap.xml"/><sqlM…

智能車復工日記【3】:圖像處理——基本掃線和基本特征提取和十字補線

博主聯系方式: QQ:1540984562 QQ交流群:892023501 群里會有往屆的smarters和電賽選手,群里也會不時分享一些有用的資料,有問題可以在群里多問問。 目錄 1、系列文章2、前言3、基本掃線(除了進入環島狀態或者坡道或者十字路口的普通掃線)1.基本數據和初步特征4、進一步特征…

short 用equals_Java Short類equals()方法的示例

short 用equals短類equals()方法 (Short class equals() method) equals() method is available in java.lang package. equals()方法在java.lang包中可用。 equals() method is used to check equality or inequality of this Object against the given Object or in other wo…

圖解MySQL數據庫的陳列和把持-4

泉源&#xff1a;網海拾貝 填入一些測試數據&#xff1a; 封閉“MySQL Query Browser”&#xff0c;再從頭翻開它&#xff0c;切換到testtable表&#xff0c;看到了沒有&#xff1f;剛剛輸出的中文變成了“&#xff1f;&#xff1f;&#xff1f;&#xff1f;&#xff1f;&am…

非常好友(C++)

Bessie和其他的所有奶牛的耳朵上都戴有一個射頻識別&#xff08;RFID&#xff09;序列號碼牌。因此農夫John可以機械化地計算他們的數量。很多奶牛都有一個“牛友”。如果奶牛A的序列號的約數之和剛好等于奶牛B的序列號&#xff0c;那么A的牛友就是B。在這里&#xff0c;一個數…