s1081050 作業1
圖像旋轉 (Image Rotation)
目錄
作業說明
撰寫一個程式將一張圖像的(a)整張圖像,(b)中心內切圓區域,旋轉一個角度(逆時針旋
轉 0 度至 359 度):利用一個滑動條(trackbar)控制旋轉角度。

開發環境
$ uname -srvmio
Linux 5.19.0-35-generic #36~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Fri Feb 17 15:17:25 UTC 2 x86_64 x86_64 GNU/Linux
$ gcc --version
gcc (Ubuntu 11.3.0-1ubuntu1~22.04) 11.3.0
$ pkg-config --modversion opencv4
4.5.4
程式碼說明
(a)整張圖片旋轉
宣告與初始化變數
// include opencv 與 stdio library
#include "opencv2/highgui.hpp"
#include "opencv2/imgcodecs.hpp"
#include <opencv2/opencv.hpp>
#include <stdio.h>
// 定義GUI視窗名稱、滑動條名稱與最大值
#define WINDOW_TITLE "Rotated image"
#define SLIDER_MAX 359
#define TRACK_BAR_NAME "Degree"
// 使用 cv namespace
using namespace cv;
//設定全域變數 src 用來儲存圖片
Mat src;
函式宣告
// 宣告一個 function 當 trackbar onchange 時執行
static void on_trackbar(int, void *)
{
// 取得Trackbar的位置(Position)
double degree = getTrackbarPos(TRACK_BAR_NAME, WINDOW_TITLE);
// 宣告一個物件用於儲存輸出矩陣
Mat output;
/* 宣告一個轉置矩陣
* 利用 getRotationMatrix2D 可以產生一個旋轉矩陣
* 第一個參數為旋轉中心,以圖片的中心為旋轉點
* 第二個參數為旋轉角度
* 第三個參數為縮放比例
*/
Mat rotation =
getRotationMatrix2D(Point2f(src.cols / 2, src.rows / 2), degree, 1);
// 矩陣重新映射至 output
warpAffine(src, output, rotation, src.size());
// 顯示 output 之影像
imshow(WINDOW_TITLE, output);
}
旋轉矩陣運作原理
M=[αβ(1−α)⋅center.x−β⋅center.y−βαβ⋅center.x+(1−α)⋅center.y]
α=scale⋅cos(angle)
β=scale⋅sin(angle)
介面控制
// 透過 argc argv 去接收圖片路徑
int main(int argc, char **argv)
{
// 當參數不為 2 時表示路徑格是錯誤
if (argc != 2) {
printf("usage: DisplayImage.out <Image_Path>\n");
return -1;
}
// 讀入路徑圖片
src = imread(argv[1], IMREAD_COLOR);
if (src.empty()) {
printf("%s", "Error loading image \n");
return -1;
}
// 命名新的視窗
namedWindow(WINDOW_TITLE, WINDOW_AUTOSIZE);
// 建立 trackbar
createTrackbar(TRACK_BAR_NAME, WINDOW_TITLE, nullptr, SLIDER_MAX,
on_trackbar);
// 設定 trackbar 位置
setTrackbarPos(TRACK_BAR_NAME, WINDOW_TITLE, 0);
// 初始化位置
on_trackbar(0, 0);
waitKey(0);
return 0;
}
(b)圖片中心旋轉
#include "opencv2/highgui.hpp"
#include "opencv2/imgcodecs.hpp"
#include <opencv2/opencv.hpp>
#include <stdio.h>
#define WINDOW_TITLE "Rotated image center"
#define SLIDER_MAX 359
#define TRACK_BAR_NAME "Degree"
#define CIRCLE_SCALE 100
using namespace cv;
Mat src;
static void on_trackbar(int, void *)
{
double degree = getTrackbarPos(TRACK_BAR_NAME, WINDOW_TITLE);
Mat mask = Mat::zeros(src.size(), src.type());
Mat rev_mask;
Mat output, middle;
Point2f center(src.cols / 2, src.rows / 2);
// 建立一個圓形圖案,並儲存至mask作為遮罩
circle(mask, center, CIRCLE_SCALE,
Scalar(255, 255, 255), FILLED);
//原圖透過遮罩後存入middle
src.copyTo(middle, mask);
//建立一個反向遮罩
bitwise_not(mask, rev_mask);
//原圖透過反向遮罩存入rev_mask
src.copyTo(output, rev_mask);
/* 現在已經將原圖拆為兩個部分
* 1.內部圓形
* 2.外部框架
*/
// 旋轉中間圓形部分
Mat rotation =
getRotationMatrix2D(center, degree, 1);
warpAffine(middle, middle, rotation, middle.size());
// 輸出旋轉後的內部圓形與外部框架之合併圖
imshow(WINDOW_TITLE, middle | output);
}
int main(int argc, char **argv)
{
// get image path from command line
if (argc != 2) {
printf("usage: DisplayImage.out <Image_Path>\n");
return -1;
}
// load image from path
src = imread(argv[1], IMREAD_COLOR);
if (src.empty()) {
printf("%s", "Error loading image \n");
return -1;
}
// create window
namedWindow(WINDOW_TITLE, WINDOW_AUTOSIZE);
createTrackbar(TRACK_BAR_NAME, WINDOW_TITLE, nullptr, SLIDER_MAX,
on_trackbar);
setTrackbarPos(TRACK_BAR_NAME, WINDOW_TITLE, 0);
// initial window
on_trackbar(0, 0);
waitKey(0);
return 0;
}
程式展示
編譯
進入資料夾

cmake .
make


執行
a
./HW1a yzu.bmp

| 初始化 | 旋轉30 | 旋轉345 |
|---|---|---|
![]() |
![]() |
![]() |
b
./HW1b yzu.bmp

| 初始化 | 旋轉43 | 旋轉270 |
|---|---|---|
![]() |
![]() |
![]() |
參考資料
cv::getRotationMatrix2D
cv:wrapAffine
cv Sample(需要從source編譯)






留言
張貼留言