課程名稱:線性代數 CS233 B
授課教師:簡廷因
發放時間:2020-11-02
截止時間:2020-11-30 23:59:59
題目說明
給一張圖片 ( jpg ),偵測出圖片中最長的直線,逆時針旋轉直到直線垂直於水平線,並將旋轉後多出來的部份塗黑,之後輸出成圖片檔 ( jpg )。
本次作業可使用 OpenCV 套件
參數設定:
Canny 使用 500,100
HoughLinesP 使用 1, CV_PI / 180, 250, 200, 10
OpenCV 設定
在Visual Studio 2019上使用OpenCV : 先依照這篇設定,之後會遇到錯誤類似於 LNK1104 無法開啟檔案 'opencv_world401d.lib'
[圖文] OpenCV 4.0.1 安裝配置在 Visual Studio 2019 : 之後再依照這篇設定環境參數即可。
解題思路
先使用 imread()
讀取圖片,之後使用 Canny()
完成邊緣偵測,再使用 HoughLinesP()
完成霍夫直線判斷,得到圖片中所有直線的陣列,之後遍歷陣列取得最長邊的斜率 ( 長度可使用 norm()
進行計算 ),並算出圖片需要旋轉的角度 ( 在 getSlope()
中 return 的地方,我也不知道為什麼要這樣弄,在網路上找的資料拼拼湊湊弄出來的 ),之後找出圖片的中心點 ( 長度寬度各除以二 ),並使用 getRotationMatrix2D()
找出旋轉矩陣,最後使用 warpAffine()
取得圖片旋轉後的結果並輸出檔案 ( 使用 imwrite()
) 即可。
請先看更新:點我
參考解法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
| #include <iostream> #include <opencv2/opencv.hpp>
using namespace std; using namespace cv;
double getSlope(vector<Vec4i>& lines) { double _max = 0, tmp; Vec4i V;
for (auto& l : lines) { tmp = norm(Point(l[2], l[3]) - Point(l[0], l[1])); if (tmp > _max) _max = tmp, V = l; }
return atan((double)(V[3] - V[1]) / (double)(V[2] - V[0])) * 180 / CV_PI + 90; }
int main(int argc, char* argv[]) { if (argc < 3) return -1;
Mat Image = imread(argv[1], -1); if (Image.empty()) return -1;
Mat canny; Canny(Image, canny, 500, 100, 3);
vector<Vec4i> Lines; HoughLinesP(canny, Lines, 1, CV_PI / 180, 250, 200, 10);
auto slope = getSlope(Lines);
Size sz = Image.size(); Point2f center(sz.width / 2., sz.height / 2.); Mat rotMat = getRotationMatrix2D(center, slope, 1.0);
Mat result; warpAffine(Image, result, rotMat, sz);
imwrite(argv[2], result); }
|
參考資料
Opencv霍夫直线检测
opencv計算直線的斜率、截距,與水平線弧度值、角度值
用OpenCV實現Photoshop算法(一): 圖像旋轉
2020/12/01 00:39
老師系統好像出問題,抓錯資料導致測資錯誤,後來系統弄好後只剩 10 分,然後多了一些需要處理的情況。
還有原本是 逆時針旋轉,後來改成 朝最接近垂直線的角度旋轉。
修改旋轉角度: 原本是逆時針旋轉所以 slope
直接加 90,後來加上判斷,若順時針旋轉的角度較小則順時針旋轉,減 90。修改這邊後是 50 分。
彩色圖片: 原本的測資好像都是黑白的圖片,所以那時候沒有加上轉灰階,新測資的 6 ~ 10 是彩色的圖片,需要轉灰階才能成功偵測。
修改後的 Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
| #include <iostream> #include <opencv2/opencv.hpp> #include <opencv2/imgproc/types_c.h>
using namespace std; using namespace cv;
double getSlope(vector<Vec4i>& lines) { double _max = 0, tmp; Vec4i V;
for (auto& l : lines) { tmp = norm(Point(l[2], l[3]) - Point(l[0], l[1])); if (tmp > _max) _max = tmp, V = l; }
return atan((double)(V[3] - V[1]) / (double)(V[2] - V[0])) * 180 / CV_PI; }
int main(int argc, char* argv[]) { if (argc < 3) return -1;
Mat Image = imread(argv[1], -1); if (Image.empty()) return -1;
Mat gray; cvtColor(Image, gray, CV_BGR2GRAY);
Mat canny; Canny(gray, canny, 500, 100, 3);
vector<Vec4i> Lines; HoughLinesP(canny, Lines, 1, CV_PI / 180, 250, 200, 10);
double slope = getSlope(Lines); slope += (slope > 0) ? -90 : 90;
Size sz = Image.size(); Point2f center(sz.width / 2., sz.height / 2.); Mat rotMat = getRotationMatrix2D(center, slope, 1.0);
Mat result; warpAffine(Image, result, rotMat, sz);
imwrite(argv[2], result); }
|