一、实验注意事项:
- 首先要进行相机标定,得到相机内参与畸变参数。
- 搭建简易拍摄平台。主要保证螺栓的稳定、相机的高度固定、光源的稳定。如下图:
二、实验步骤:
1、使用棋盘标定相机,得到相机的内参与畸变矩阵。这里不赘述。
2、布置实验平台
布置理由:
|
/3、拍摄标准1元硬币图片,得到实际尺寸25,mm对应的图像尺寸;结果如下图:
所以比例尺为275/25=11(equivalence).
3、拍摄螺栓图像,编写程序识别---程序与第二部无太多差别。然后程序判断此螺栓为什么规格,进行输出。
结果:
原图形---修正后的图像---开运算---边缘检测---画圆形---判断结果
#include "opencv2/core/core.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/calib3d/calib3d.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/opencv.hpp"
#include <iostream>
using namespace cv;
using namespace std;
Mat src_image;
//修复图像畸变
void realImage()
{
Mat cameraMatrix = Mat::eye(3, 3, CV_64F);
//相机内参矩阵--参数为事先得到
cameraMatrix.at<double>(0, 0) = 1.12118872e+003;
cameraMatrix.at<double>(0, 1) = 0;
cameraMatrix.at<double>(0, 2) = 7.22370911e+002;
cameraMatrix.at<double>(1, 0) = 0;
cameraMatrix.at<double>(1, 1) = 1.11967517e+003;
cameraMatrix.at<double>(1, 2) = 5.50119080e+002;
cameraMatrix.at<double>(2, 0) = 0;
cameraMatrix.at<double>(2, 1) = 0;
cameraMatrix.at<double>(2, 2) = 1;
//相机畸变参数--参数为事先得到
Mat distCoeffs = Mat::zeros(5, 1, CV_64F);
distCoeffs.at<double>(0, 0) = 0.183161348;
distCoeffs.at<double>(1, 0) = -0.358715266;
distCoeffs.at<double>(2, 0) = 0.00630304869;
distCoeffs.at<double>(3, 0) = -0.00271669053;
distCoeffs.at<double>(4, 0) = 0;
src_image = imread("1.jpg", 0);
namedWindow("原图形", WINDOW_NORMAL);
imshow("原图形", src_image);
Mat map1, map2;
Size imageSize;
imageSize = src_image.size();
//得到map1,map2
initUndistortRectifyMap(cameraMatrix, distCoeffs, Mat(), getOptimalNewCameraMatrix(cameraMatrix, distCoeffs, imageSize, 1, imageSize, 0),
imageSize, CV_16SC2, map1, map2);
//重映射---修复畸变
remap(src_image, src_image, map1, map2, INTER_LINEAR);
namedWindow("修正后的图像", WINDOW_NORMAL);
imshow("修正后的图像", src_image);
}
void main()
{
//修复图像畸变
realImage();
//为标准1元硬币图像半径值与实际半径值的比值
double equivalence = 11;
double trueDistance;
//均值滤波
blur(src_image, src_image, Size(3, 3));
//开运算 把物体表面的字给去掉了
Mat ele = getStructuringElement(MORPH_RECT, Size(8, 8));
morphologyEx(src_image, src_image, MORPH_OPEN, ele);
namedWindow("开运算", WINDOW_NORMAL);
imshow("开运算", src_image);
//边缘检测
Canny(src_image, src_image, 20, 50);
namedWindow("边缘检测", WINDOW_NORMAL);
imshow("边缘检测", src_image);
//圆型检测
vector<Vec3f>circles;
HoughCircles(src_image, circles, CV_HOUGH_GRADIENT, 1.5, 800, 100, 100, 0,200);
printf("圆的个数为%d", circles.size());
//画圆形
unsigned int a = 0;
for (a; a< circles.size(); a++)
{
Point center(cvRound(circles[a][0]), cvRound(circles[a][1]));
int radius = cvRound(circles[a][2]);
circle(src_image, center, 3, Scalar(0, 255, 0), -1, 8, 0);
circle(src_image, center, radius, Scalar(255, 134, 0), 3, 8, 0);
//比例换算
trueDistance = circles[a][2] / equivalence;
//判断是什么规格螺栓
switch (cvRound(trueDistance))
{
case 6:
printf("\n螺栓规格为M3");
break;
case 7:
printf("\n螺栓规格为M4");
break;
case 9:
printf("\n螺栓规格为M5");
break;
case 10:
printf("\n螺栓规格为M6");
break;
case 13:
printf("\n螺栓规格为M8");
break;
case 16:
printf("\n螺栓规格为M10");
break;
}
//输出半径大小
printf("\n圆的实际半径大小为 %lf", trueDistance);
}
namedWindow("画圆形", WINDOW_NORMAL);
imshow("画圆形", src_image);
waitKey(0);
}
三、项目其中仍然需要解决的问题:
1、相机标定的内参与畸变矩阵有时对部分图片矫准错误,图片都扭曲了。即是加大了标定棋盘照片数量也不行。怀疑和照片大小有关系,需要验证。
2、houghcircles函数并不能固定参数,试验其他规格的螺栓时,还需要手动调整函数关键参数,这肯定不完美,需要进一步思考解决。