owned this note
owned this note
Published
Linked with GitHub
---
title: 'CS362 Assignment #1'
disqus: hackmd
---
圖像旋轉 (Image Rotation)
===
## 目錄
[TOC]
## 作業說明
撰寫一個程式將一張圖像的(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)整張圖片旋轉
#### 宣告與初始化變數
```cpp=1
// 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;
```
#### 函式宣告
```cpp=17
// 宣告一個 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 = \begin{bmatrix} \alpha & \beta & (1- \alpha ) \cdot \texttt{center.x} - \beta \cdot \texttt{center.y} \\ - \beta & \alpha & \beta \cdot \texttt{center.x} + (1- \alpha ) \cdot \texttt{center.y} \end{bmatrix}$
$α = scale ⋅ cos(angle)$
$β = scale ⋅ sin(angle)$
#### 介面控制
```cpp=37
// 透過 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)圖片中心旋轉
```gcc=1
#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;
}
```
## 程式展示
### 編譯
進入資料夾

```bash=
cmake .
make
```


### 執行
#### a
```bash=
./HW1a yzu.bmp
```

| 初始化 | 旋轉30 | 旋轉345 |
| -------- | -------- | -------- |
| |  |  |
#### b
```bash=
./HW1b yzu.bmp
```

| 初始化 | 旋轉43 | 旋轉270 |
| -------- | -------- | -------- |
| |  |  |
## 參考資料
[cv::getRotationMatrix2D](https://docs.opencv.org/4.7.0/da/d54/group__imgproc__transform.html#gafbbc470ce83812914a70abfb604f4326)
[cv:wrapAffine](https://docs.opencv.org/4.7.0/da/d54/group__imgproc__transform.html#ga0203d9ee5fcd28d40dbc4a1ea4451983)
cv Sample(需要從source編譯)
###### tags: `CS362` `s1081050` `HW1`