欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

基于OpenCV和C++ 實(shí)現(xiàn)圖片旋轉(zhuǎn)

 更新時(shí)間:2020年12月15日 11:54:23   作者:IronYoung  
這篇文章主要介紹了基于OpenCV和C++ 實(shí)現(xiàn)圖片旋轉(zhuǎn),幫助大家更好的利用c++處理圖片,感興趣的朋友可以了解下

圖片旋轉(zhuǎn),本質(zhì)上是對(duì)旋轉(zhuǎn)后的圖片中每個(gè)像素點(diǎn)計(jì)算在原圖的位置。然后照搬過(guò)來(lái)就好。

(多說(shuō)一句,如果計(jì)算出來(lái)在原圖中的位置不是整數(shù)而是小數(shù),因?yàn)橄袼攸c(diǎn)個(gè)數(shù)都是整數(shù),就需要小數(shù)到整數(shù)的轉(zhuǎn)換。這個(gè)轉(zhuǎn)換過(guò)程是有講究的,需要用到插值:最近鄰插值、雙線性插值等等。這里我使用的是最簡(jiǎn)單的最近鄰插值,即對(duì)小數(shù)四舍五入成整數(shù),C/C++ 實(shí)現(xiàn)四舍五入見(jiàn) 這里 )

圖形圖像課上一般會(huì)介紹旋轉(zhuǎn)變換矩陣,其中 t 為需要旋轉(zhuǎn)的角度,[x'; y']是變換后坐標(biāo)(其中分號(hào)表示上下關(guān)系):

即表示為:[x'; y'] = [cos(t) sin(t); -sin(t) cos(t)][x; y]

因?yàn)槲覀€(gè)人興趣愛(ài)好(放P就是老師逼的。。。),不允許使用 OpenCV 封裝好的旋轉(zhuǎn)函數(shù)。只能自己實(shí)現(xiàn),我開(kāi)始的想法是:先求變換矩陣逆矩陣,然后將一張全黑圖中每個(gè)點(diǎn)一一對(duì)應(yīng)插值到原圖中。

結(jié)果發(fā)現(xiàn)轉(zhuǎn)換后圖片全黑了……

后來(lái)發(fā)現(xiàn)原點(diǎn)設(shè)置不對(duì)。用OpenCV中的 Mat格式存儲(chǔ)(或二維數(shù)組)的圖片, 原點(diǎn)在左上角 。但是想要實(shí)現(xiàn)的 旋轉(zhuǎn)原點(diǎn)在圖片中心 。

同時(shí), Mat格式存儲(chǔ)(或二維數(shù)組)的 坐標(biāo)系中 y軸正方向向下 。這樣人類(lèi)視覺(jué)上的順時(shí)針旋轉(zhuǎn),在二維數(shù)組的坐標(biāo)系中是逆時(shí)針旋轉(zhuǎn)。

最重要的一點(diǎn),也是二維數(shù)組操作中極易忽略的一點(diǎn): 數(shù)組操作的是 數(shù)組下標(biāo) ,不是坐標(biāo)系(數(shù)組的行數(shù) rows 是矩形的寬 width ,列數(shù) cols 是矩形的長(zhǎng) length ) 。比如坐標(biāo)系(此時(shí)為了更貼近數(shù)組布局,我們 假設(shè) y 軸坐標(biāo)系是向下的 )中,矩形頂點(diǎn)是:

但是在數(shù)組中,因?yàn)槭切袃?yōu)先,所以四個(gè)點(diǎn)的下標(biāo)取值為:

有沒(méi)有發(fā)現(xiàn),兩種坐標(biāo)是相反的!

總結(jié)下來(lái),我們的圖片旋轉(zhuǎn)需要注意以下幾點(diǎn):

  1. 變換后圖片中的每個(gè)像素點(diǎn)(i; j),需要平移到相對(duì)旋轉(zhuǎn)中心的新坐標(biāo),即(i - Mat.rows/2; j - Mat.cols/2)。計(jì)算完成之后,需要再次 還原 到相對(duì)左上角原點(diǎn)的舊坐標(biāo);
  2. 本來(lái)需要 變換后圖片 乘以 原圖 變換矩陣的 逆矩陣 對(duì)應(yīng)到原圖中坐標(biāo)。但是因?yàn)閥軸方向向下,所以 變換后圖片 乘以 原圖 變換矩陣(無(wú)需逆矩陣) 即可對(duì)應(yīng)到原圖中坐標(biāo)(順時(shí)針旋轉(zhuǎn)50度,還原操作是逆時(shí)針旋轉(zhuǎn)50度);
  3. 矩陣下標(biāo)與原圖變換矩陣相乘之前,需要將矩陣 下標(biāo)兩值互換 。相乘之后,需要 再次互換下標(biāo)值 還原成矩陣下標(biāo)。

因此對(duì)于一個(gè)經(jīng)過(guò)旋轉(zhuǎn) t 度之后 數(shù)組下標(biāo) 為[m‘, n']的像素值,還原成原圖中的 數(shù)組下標(biāo) [m; n]計(jì)算為:

[cos(t) -sin(t); sin(t) cos(t)] ([m'; n'] - [Mat.rows/2; Mat.cols/2]) = [m; n] -  [Mat.rows/2; Mat.cols/2]

源代碼附上:

Mat nearestNeighRotate(cv::Mat img, float angle)
{
	int len = (int)(sqrtf(pow(img.rows, 2) + pow(img.cols, 2)) + 0.5);

	Mat retMat = Mat::zeros(len, len, CV_8UC3);
	float anglePI = angle * CV_PI / 180;
	int xSm, ySm;

	for(int i = 0; i < retMat.rows; i++)
		for(int j = 0; j < retMat.cols; j++)
		{
			xSm = (int)((i-retMat.rows/2)*cos(anglePI) - (j-retMat.cols/2)*sin(anglePI) + 0.5);
			ySm = (int)((i-retMat.rows/2)*sin(anglePI) + (j-retMat.cols/2)*cos(anglePI) + 0.5);
			xSm += img.rows / 2;
			ySm += img.cols / 2;

			if(xSm >= img.rows || ySm >= img.cols || xSm <= 0 || ySm <= 0){
				retMat.at<Vec3b>(i, j) = Vec3b(0, 0);
			}
			else{
				retMat.at<Vec3b>(i, j) = img.at<Vec3b>(xSm, ySm);
			}
		}

	return retMat;
}

好,我們來(lái)測(cè)試看看:

int main() 
{ 
	Mat img = imread("../HelloWorld.png");
	retImg = nearestNeighRotate(img, -20.f);
	namedWindow("nearNeigh", CV_WINDOW_AUTOSIZE);
	imshow("nearNeigh", retImg);

	waitKey(); 
	cvDestroyAllWindows();
	return 0; 
}

結(jié)果(旋轉(zhuǎn)了20度)為

以上就是基于OpenCV和C++ 實(shí)現(xiàn)圖片旋轉(zhuǎn)的詳細(xì)內(nèi)容,更多關(guān)于c++ 圖片旋轉(zhuǎn)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • C語(yǔ)言的結(jié)構(gòu)體你了解嗎

    C語(yǔ)言的結(jié)構(gòu)體你了解嗎

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言的結(jié)構(gòu)體,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助
    2022-02-02
  • C++深拷貝與淺拷貝的區(qū)別及應(yīng)用

    C++深拷貝與淺拷貝的區(qū)別及應(yīng)用

    這篇文章主要給大家介紹了關(guān)于C++深拷貝與淺拷貝區(qū)別及應(yīng)用的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04
  • 怎么在C++二進(jìn)制文件中注入git信息詳解

    怎么在C++二進(jìn)制文件中注入git信息詳解

    這篇文章主要給大家介紹了關(guān)于怎么在C++二進(jìn)制文件中注入git信息的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2021-06-06
  • 淺析C/C++中sort函數(shù)的用法

    淺析C/C++中sort函數(shù)的用法

    做項(xiàng)目的時(shí)候,排序是一種經(jīng)常要用到的操作。如果每次都自己寫(xiě)個(gè)冒泡之類(lèi)的O(n^2)排序,不但程序容易超時(shí),而且浪費(fèi)寶貴的時(shí)間,還很有可能寫(xiě)錯(cuò)。STL里面有個(gè)sort函數(shù),可以直接對(duì)數(shù)組排序,復(fù)雜度為n*log2(n)。
    2014-09-09
  • VC實(shí)現(xiàn)對(duì)話框窗口任意分割

    VC實(shí)現(xiàn)對(duì)話框窗口任意分割

    最近寫(xiě)MFC的程序,想在對(duì)話框里實(shí)現(xiàn)窗口的任意分割?,F(xiàn)在網(wǎng)絡(luò)資料一大抄,找個(gè)東西實(shí)在麻煩??偹氵@個(gè)很簡(jiǎn)單,很快就搞定了,寫(xiě)下來(lái)做個(gè)筆記。
    2015-06-06
  • C語(yǔ)言實(shí)現(xiàn)旅游景點(diǎn)咨詢(xún)系統(tǒng)

    C語(yǔ)言實(shí)現(xiàn)旅游景點(diǎn)咨詢(xún)系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)旅游景點(diǎn)咨詢(xún)系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-12-12
  • C++ stack與queue使用方法詳細(xì)講解

    C++ stack與queue使用方法詳細(xì)講解

    stack是一種容器適配器,專(zhuān)門(mén)用在具有后進(jìn)先出操作的上下文環(huán)境中,其刪除只能從容器的一端進(jìn)行 元素的插入與提取操作;隊(duì)列是一種容器適配器,專(zhuān)門(mén)用于在FIFO上下文(先進(jìn)先出)中操作,其中從容器一端插入元素,另一端提取元素
    2023-01-01
  • 使用C++的ORM框架QxORM詳解

    使用C++的ORM框架QxORM詳解

    這篇文章主要介紹了使用C++的ORM框架QxORM的相關(guān)知識(shí),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-06-06
  • 超級(jí)詳細(xì)講解C++中的多態(tài)

    超級(jí)詳細(xì)講解C++中的多態(tài)

    多態(tài)是在不同繼承關(guān)系的類(lèi)對(duì)象,去調(diào)同一函數(shù),產(chǎn)生了不同的行為,下面這篇文章主要給大家介紹了關(guān)于C++中多態(tài)的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-05-05
  • C語(yǔ)言三分鐘精通時(shí)間復(fù)雜度與空間復(fù)雜度

    C語(yǔ)言三分鐘精通時(shí)間復(fù)雜度與空間復(fù)雜度

    算法復(fù)雜度分為時(shí)間復(fù)雜度和空間復(fù)雜度。其作用:?時(shí)間復(fù)雜度是度量算法執(zhí)行的時(shí)間長(zhǎng)短;而空間復(fù)雜度是度量算法所需存儲(chǔ)空間的大小
    2022-02-02

最新評(píng)論