Skip to content

Commit 08d0ccb

Browse files
committed
Add angle detection infomation. Bugs fixed
1 parent 1159d6c commit 08d0ccb

9 files changed

+316
-46
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
/*
2+
* This file is used to calibrate a new camera to get its
3+
* corresponding intrinsic and extrinsic parameters.
4+
* Four files will be saved at the same path as this file
5+
* if the calibration process turns out to be successful.
6+
*/
7+
8+
#include <opencv2/opencv.hpp>
9+
#include <stdio.h>
10+
#include <iostream>
11+
12+
using namespace std;
13+
14+
15+
void writeMatToFile(const cv::Mat& m, const string& filename);
16+
17+
// Defining the dimensions of checkerboard
18+
int CHECKERBOARD[2]{ 9,6 };
19+
20+
// Define length of a grid (mm)
21+
double gridLength = 143. / 5.;
22+
23+
int __my_main()
24+
{
25+
// Creating vector to store vectors of 3D points for each checkerboard image
26+
// 创建矢量以存储每个棋盘图像的三维点矢量
27+
vector<vector<cv::Point3f> > objpoints;
28+
29+
// Creating vector to store vectors of 2D points for each checkerboard image
30+
// 创建矢量以存储每个棋盘图像的二维点矢量
31+
vector<vector<cv::Point2f> > imgpoints;
32+
33+
// Defining the world coordinates for 3D points
34+
// 为三维点定义世界坐标系
35+
vector<cv::Point3f> objp;
36+
for (int i{ 0 }; i < CHECKERBOARD[1]; i++)
37+
{
38+
for (int j{ 0 }; j < CHECKERBOARD[0]; j++)
39+
{
40+
objp.push_back(cv::Point3f(j*gridLength, i*gridLength, 0));
41+
}
42+
}
43+
44+
// Extracting path of individual image stored in a given directory
45+
// 提取存储在给定目录中的单个图像的路径
46+
vector<cv::String> images;
47+
48+
// Path of the folder containing checkerboard images
49+
// 包含棋盘图像的文件夹的路径, 根据实际情况修改文件夹路径,
50+
// 标定过程需相机拍摄10~12张包含完整棋盘格的不同的图片。
51+
string path = ".\\imagesForCalib\\*.bmp";
52+
53+
// 使用glob函数读取所有图像的路径
54+
cv::glob(path, images);
55+
for (int i = 0; i < images.size(); i++)
56+
cout << images[i] << endl;
57+
58+
59+
cv::Mat frame, gray;
60+
61+
// vector to store the pixel coordinates of detected checker board corners
62+
// 存储检测到的棋盘转角像素坐标的矢量
63+
vector<cv::Point2f> corner_pts;
64+
bool success;
65+
66+
// Looping over all the images in the directory
67+
// 循环读取图像
68+
for (int i{ 0 }; i < images.size(); i++)
69+
{
70+
frame = cv::imread(images[i]);
71+
cv::resize(frame, frame, cv::Size(int(frame.size().width / 3), int(frame.size().height / 3)));
72+
if (frame.empty())
73+
{
74+
continue;
75+
}
76+
if (i == 40)
77+
{
78+
int b = 1;
79+
}
80+
cout << "the current image is " << i << "th" << endl;
81+
cv::cvtColor(frame, gray, cv::COLOR_BGR2GRAY);
82+
83+
// Finding checker board corners
84+
// 寻找角点
85+
// If desired number of corners are found in the image then success = true
86+
// 如果在图像中找到所需数量的角,则success = true
87+
// opencv4以下版本,flag参数为CV_CALIB_CB_ADAPTIVE_THRESH | CV_CALIB_CB_FAST_CHECK | CV_CALIB_CB_NORMALIZE_IMAGE
88+
success = cv::findChessboardCorners(gray, cv::Size(CHECKERBOARD[0], CHECKERBOARD[1]), corner_pts,
89+
cv::CALIB_CB_ADAPTIVE_THRESH | cv::CALIB_CB_FAST_CHECK | cv::CALIB_CB_NORMALIZE_IMAGE);
90+
91+
/*
92+
* If desired number of corner are detected,
93+
* we refine the pixel coordinates and display
94+
* them on the images of checker board
95+
*/
96+
97+
// 如果检测到所需数量的角点,我们将细化像素坐标并将其显示在棋盘图像上
98+
if (success)
99+
{
100+
// 如果是OpenCV4以下版本,第一个参数为CV_TERMCRIT_EPS | CV_TERMCRIT_ITER
101+
cv::TermCriteria criteria(cv::TermCriteria::EPS | cv::TermCriteria::Type::MAX_ITER, 30, 0.001);
102+
103+
// refining pixel coordinates for given 2d points.
104+
// 为给定的二维点细化像素坐标
105+
cv::cornerSubPix(gray, corner_pts, cv::Size(11, 11), cv::Size(-1, -1), criteria);
106+
107+
// Displaying the detected corner points on the checker board
108+
// 在棋盘上显示检测到的角点
109+
cv::drawChessboardCorners(frame, cv::Size(CHECKERBOARD[0], CHECKERBOARD[1]), corner_pts, success);
110+
111+
objpoints.push_back(objp);
112+
imgpoints.push_back(corner_pts);
113+
}
114+
115+
string winName = "Image" + to_string(i);
116+
//cv::Mat showFame;
117+
//cv::Size showSize(int(frame.size().width / 3), int(frame.size().height / 3));
118+
//cv::resize(frame, showFame, showSize);
119+
cv::imshow(winName, frame);
120+
}
121+
122+
cv::Mat cameraMatrix, distCoeffs, R, T;
123+
124+
/*
125+
* Performing camera calibration by
126+
* passing the value of known 3D points (objpoints)
127+
* and corresponding pixel coordinates of the
128+
* detected corners (imgpoints)
129+
*/
130+
// 通过传递已知3D点(objpoints)的值和检测到的角点(imgpoints)的相应像素坐标来执行相机校准
131+
cv::calibrateCamera(objpoints, imgpoints, cv::Size(gray.rows, gray.cols), cameraMatrix, distCoeffs, R, T);
132+
133+
cout << endl;
134+
// 内参矩阵
135+
cout << "cameraMatrix : " << endl << cameraMatrix << endl << endl;
136+
// 透镜畸变系数
137+
cout << "distCoeffs : " << endl << distCoeffs << endl << endl;
138+
// rvecs
139+
cout << "Rotation vector : " << R.channels() << endl << R << endl << endl;
140+
// tvecs
141+
cout << "Translation vector : " << endl << T << endl << endl;
142+
143+
// write MATs to file
144+
string filename = ".\\intrinsicParam.txt";
145+
writeMatToFile(cameraMatrix, filename);
146+
filename = ".\\distCoeffs.txt";
147+
writeMatToFile(distCoeffs, filename);
148+
filename = ".\\rVect.txt";
149+
writeMatToFile(R.reshape(1, 0), filename);
150+
filename = ".\\tVect.txt";
151+
writeMatToFile(T.reshape(1, 0), filename);
152+
153+
// show images
154+
cv::waitKey(0);
155+
cv::destroyAllWindows();
156+
return 0;
157+
}
158+
159+
160+
//int main()
161+
//{
162+
// __my_main();
163+
// return 0;
164+
//}
165+
//
166+
//
167+
//void writeMatToFile(const cv::Mat& m, const string& filename)
168+
//{
169+
// ofstream fout(filename);
170+
//
171+
// if (!fout)
172+
// {
173+
// cout << "File Not Opened" << endl;
174+
// return;
175+
// }
176+
//
177+
// for (int i = 0; i < m.rows; i++)
178+
// {
179+
// for (int j = 0; j < m.cols; j++)
180+
// {
181+
// fout << m.at<double>(i, j) << " ";
182+
// }
183+
// fout <<endl;
184+
// }
185+
//
186+
// fout.close();
187+
// cout << "File Written Succes." << endl;
188+
//}

WorkpieceIdentification/MyDetector.cpp

+23-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include "MyDetector.h"
22
#include <cmath>
3+
#include <iostream>
34

45
double euc_distance(double arr1[], double arr2[], int len)
56
{
@@ -64,7 +65,8 @@ cv::Point MyDetector::getCentroid(std::vector<cv::Point> contour)
6465

6566
int MyDetector::sampleRadiusAndClassify(cv::Mat roi)
6667
{
67-
int width = roi.size().width, height = roi.size().height;
68+
int width = roi.size().width;
69+
int height = roi.size().height;
6870
if (width > height)
6971
{
7072
cv::transpose(roi, roi);
@@ -150,7 +152,6 @@ MyDetector::MyDetector()
150152
}
151153

152154

153-
154155
Workpiece MyDetector::getInstanceInfo(cv::Mat img, std::vector<cv::Point> contour)
155156
{
156157
using namespace std;
@@ -167,13 +168,25 @@ Workpiece MyDetector::getInstanceInfo(cv::Mat img, std::vector<cv::Point> contou
167168
vector<vector<Point>> tmp_c;
168169
tmp_c.push_back(contour);
169170
drawContours(contour_img, tmp_c, -1, Scalar(255), -1);
171+
170172
if (45 < abs(angle) && abs(angle) < 90)
171173
{
172174
angle = roRect.angle + 90;
173175
roHeight = roRect.size.width;
174176
roWidth = roRect.size.height;
175177
}
176178

179+
// Decide whether to discard this target by its side ratio.
180+
float biggerSide = roRect.size.width > roRect.size.height ? roRect.size.width : roRect.size.height;
181+
float smallerSide = roRect.size.width < roRect.size.height ? roRect.size.width : roRect.size.height;
182+
float ratio = biggerSide / smallerSide;
183+
if (ratio < 3.5 || ratio > 5)
184+
{
185+
info.cls = -1;
186+
return info;
187+
}
188+
189+
// Judge whether the rotated rect is out of bound.
177190
if (center.x - roWidth / 2 - 1 < 0 || center.y - roHeight / 2 - 1 < 0 ||
178191
center.x + roWidth / 2 + 2 >= img.size().width || center.y + roHeight / 2 + 2 >= img.size().height)
179192
{
@@ -183,13 +196,21 @@ Workpiece MyDetector::getInstanceInfo(cv::Mat img, std::vector<cv::Point> contou
183196

184197
Mat ROI;
185198
if (angle == 0)
199+
{
186200
ROI = contour_img(Rect(center.x - roWidth / 2, center.y - roHeight / 2, roWidth + 2, roHeight + 2));
201+
}
187202
else
188203
{
189204
Mat M = getRotationMatrix2D(center, angle, 1), warpped;
190205
warpAffine(contour_img, warpped, M, contour_img.size());
191206
ROI = warpped(Rect(center.x - roWidth / 2, center.y - roHeight / 2, roWidth + 2, roHeight + 2));
192207
}
208+
209+
// Calculate the angle between the horizontal line and the major axis of roRect
210+
if (roRect.size.width >= roRect.size.height)
211+
info.angle = - roRect.angle;
212+
else
213+
info.angle = 90 - roRect.angle;
193214
info.contour = contour;
194215
info.centroid = center;
195216
info.minAreaRect = roRect;

WorkpieceIdentification/MyDetector.h

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ class Workpiece
1515
cv::Point centroid;
1616
std::vector<cv::Point> contour;
1717
cv::RotatedRect minAreaRect;
18+
double angle; //in degree
1819
int cls;
1920
};
2021

WorkpieceIdentification/MyLocator.cpp

+53-7
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,38 @@
11
#include"MyLocator.h"
22

33
using namespace std;
4-
using namespace cv;
4+
5+
////int direction:
6+
////1-upward / 2-downward / 3-leftward / 4-rightward
7+
//void drawArrow(cv::Mat& img, cv::Point2f& startPt, cv::Point2f& endPt, int direction)
8+
//{
9+
// cv::Point2f end1, end2;
10+
// if (1 == direction)
11+
// {
12+
// end1 = cv::Point2f(endPt.x - 30, endPt.y + 30);
13+
// end2 = cv::Point2f(endPt.x + 30, endPt.y + 30);
14+
// }
15+
// else if (2 == direction)
16+
// {
17+
// end1 = cv::Point2f(endPt.x - 30, endPt.y - 30);
18+
// end2 = cv::Point2f(endPt.x + 30, endPt.y - 30);
19+
// }
20+
// else if (3 == direction)
21+
// {
22+
// end1 = cv::Point2f(endPt.x + 30, endPt.y - 30);
23+
// end2 = cv::Point2f(endPt.x + 30, endPt.y + 30);
24+
// }
25+
// else if (4 == direction)
26+
// {
27+
// end1 = cv::Point2f(endPt.x - 30, endPt.y - 30);
28+
// end2 = cv::Point2f(endPt.x - 30, endPt.y + 30);
29+
// }
30+
// else return;
31+
//
32+
// cv::line(img, startPt, endPt, CV_RGB(255, 255, 0), 2);
33+
// cv::line(img, endPt, end1, CV_RGB(255, 255, 0), 2);
34+
// cv::line(img, endPt, end2, CV_RGB(255, 255, 0), 2);
35+
//}
536

637

738
void writeMatToFile(const cv::Mat& m, const string& filename)
@@ -25,8 +56,8 @@ void writeMatToFile(const cv::Mat& m, const string& filename)
2556
cout << "File Written Succes." << endl;
2657
}
2758

28-
29-
bool MyLocator::calibrateCameraInit(const string& imgPath)//string imgPath = "D:\\1GraduationPrj\\cproject\\*.bmp";
59+
//string imgPath = "D:\\1GraduationPrj\\cproject\\*.bmp";
60+
bool MyLocator::calibrateCameraInit(const string& imgPath)
3061
{
3162
vector<cv::String> images;
3263
cv::glob(imgPath, images);
@@ -59,10 +90,10 @@ bool MyLocator::calibrateCameraInit(const string& imgPath)//string imgPath = "D:
5990
cv::cvtColor(frame, gray, cv::COLOR_BGR2GRAY);
6091

6192
success = cv::findChessboardCorners(gray, cv::Size(CHECKERBOARD[0], CHECKERBOARD[1]), cornerPt,
62-
CALIB_CB_ADAPTIVE_THRESH | CALIB_CB_FAST_CHECK | CALIB_CB_NORMALIZE_IMAGE);
93+
cv::CALIB_CB_ADAPTIVE_THRESH | cv::CALIB_CB_FAST_CHECK | cv::CALIB_CB_NORMALIZE_IMAGE);
6394
if (success)
6495
{
65-
cv::TermCriteria criteria(TermCriteria::EPS | TermCriteria::Type::MAX_ITER, 30, 0.001);
96+
cv::TermCriteria criteria(cv::TermCriteria::EPS | cv::TermCriteria::Type::MAX_ITER, 30, 0.001);
6697
cv::cornerSubPix(gray, cornerPt, cv::Size(11, 11), cv::Size(-1, -1), criteria);
6798
cv::drawChessboardCorners(frame, cv::Size(CHECKERBOARD[0], CHECKERBOARD[1]), cornerPt, success);
6899
objpoints.push_back(objPt);
@@ -99,6 +130,7 @@ bool MyLocator::calibrateSingleImage(cv::Mat img)
99130
if (intrinsicMat.empty() || distCoeffs.empty()) {
100131
return false;
101132
}
133+
102134
cv::Mat gray;
103135
vector<cv::Point3f> objPts, worldPts;
104136
vector<cv::Point2f> imgPts, cornerPts;
@@ -125,15 +157,29 @@ bool MyLocator::calibrateSingleImage(cv::Mat img)
125157
cv::Rodrigues(rVec, rotMat);//Transform rVec to rotMat
126158
cv::projectPoints(objPts, rVec, tVec, intrinsicMat, distCoeffs, imgPts);
127159
estimateS(imgPts); //estimate S coeff
160+
161+
//Draw info for visualization
162+
string drawText[4];
163+
drawText[0] = "(" + to_string(0) + "," + to_string(0) + ")";
164+
drawText[1] = "(" + to_string(int(gridLength * 5)) + "," + to_string(0) + ")";
165+
drawText[2] = "(" + to_string(0) + "," + to_string(int(gridLength * 3)) + ")";
166+
drawText[3] = "(" + to_string(int(gridLength * 5)) + "," + to_string(int(gridLength * 3)) + ")";
167+
128168
for (int i = 0; i < imgPts.size(); i++) {
129169
cv::circle(img, imgPts[i], 20, CV_RGB(255, 0, 0), -1);
170+
cv::putText(img, drawText[i], imgPts[i], cv::FONT_HERSHEY_PLAIN, 6, CV_RGB(255, 0, 0), 6);
130171
}
172+
cv::line(img, imgPts[0], imgPts[1], CV_RGB(255, 255, 0), 10);
173+
cv::line(img, imgPts[0], imgPts[2], CV_RGB(255, 255, 0), 10);
131174
cv::Mat showImg;
132175
cv::resize(img, showImg, cv::Size(resolution.width / 3, resolution.height / 3));
133-
cv::imwrite("./result_calibrateSingleImage.jpg", showImg);
176+
177+
cv::putText(showImg, "Coordinates are displayed in (X, Y).", cv::Point2f(10, 30), cv::FONT_HERSHEY_PLAIN, 2, CV_RGB(255, 255, 0), 2);
178+
cv::imwrite("result_calibrateSingleImage.jpg", showImg);
134179
return true;
135180
}
136-
else { return false; }
181+
else
182+
return false;
137183
}
138184

139185
void MyLocator::estimateS(const vector<cv::Point2f> &imgPts)

0 commit comments

Comments
 (0)