課程名稱:線性代數 CS233 B
授課教師:簡廷因
發放時間:2020-12-22
截止時間:2020-01-19 23:59:59


題目說明

本次的作業是影像測距,給一個固定長度的物體,推算其距離。( 利用 data.jpg 算出焦距後套用至所有的測資檢測 )

本次作業可使用 OpenCV 套件

解題思路

照著 HW4.v1.pdf 的說明步驟完成即可。

參考解法

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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/imgproc/types_c.h>

using namespace std;
using namespace cv;

/*
reference:
findContours ( 尋找輪廓 ): https://ppt.cc/fchOEx
contourArea ( 計算輪廓面積 ): https://ppt.cc/fqIYtx
approxPolyDP ( 逼近邊緣 ): https://ppt.cc/f0FApx
minAreaRect ( 最佳邊框 ): https://ppt.cc/f45Axx
*/

/* 指定參數
GaussianBlur(matrix, matrix, Size(5, 5), 0);
Canny(matrix, out_ matrix, 35, 125);
findContours(matrix, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE);
approxPolyDP(contours, contours_poly, 3, true);
*/

// 取得面積最大的輪廓
vector<Point> GetBiggestContours(vector<vector<Point>>& contours);
double Distance(Point2f& l, Point2f& r);

int main(int argc, char* argv[])
{
Mat img = imread(argv[1]);

// 轉灰階
Mat gray;
cvtColor(img, gray, CV_BGR2GRAY);

// 高斯模糊
Mat Gauss;
GaussianBlur(gray, Gauss, Size(5, 5), 0);

Mat canny;
Canny(Gauss, canny, 35, 125);

// 找輪廓
vector<vector<Point>> contours; // contours (n.) 輪廓; 外型; 曲線
findContours(canny, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE);

// 取得面積最大的輪廓
auto MaxContours = GetBiggestContours(contours);

// 逼近邊緣
vector<Point> contours_poly;
approxPolyDP(MaxContours, contours_poly, 3, true);

// 取得最佳邊框
auto rect = minAreaRect(contours_poly);
Point2f boxPoints[4];
rect.points(boxPoints);

// 像素寬度
auto width = Distance(boxPoints[0], boxPoints[3]);

//// 焦距 -> 3752.24
//auto fl = (width * 1500) / 210;

auto l = (210 * 3752.24) / width;

cout << l << '\n';
}

// 取得面積最大的輪廓
vector<Point> GetBiggestContours(vector<vector<Point>>& contours)
{
vector<Point> biggest;
double _max = 0;
for (auto& v : contours)
{
auto tmp = contourArea(v);
if (tmp > _max) _max = tmp, biggest = v;
}
return biggest;
}

double Distance(Point2f& l, Point2f& r)
{
double dx = r.x - l.x;
double dy = r.y - l.y;
return sqrt(dx * dx + dy * dy);
}

參考資料

findContours 實作(OpenCV)
[OpenCV] 計算輪廓面積 (Calculate Contour Area) | 逍遙文工作室
OpenCV approxPolyDP()函数详解_高祥xiang的博客-CSDN博客
Opencv獲取最小外接矩形——minAreaRect - IT閱讀