源码已经上传[https://gitee.com/facebaby_L/instrument_recognition.git]https://gitee.com/facebaby_L/instrument_recognition.git)
核心函数
//边缘检测
void Canny(InputArray image,OutputArray edges, double threshold1, double threshold2, int apertureSize=3,bool L2gradient=false )
-
InputArray类型的image,输入图像,即源图像,填Mat类的对象即可,且需为单通道8位图像。
-
OutputArray类型的edges,输出的边缘图,需要和源图片有一样的尺寸和类型。
-
double类型的threshold1,第一个滞后性阈值【低阈值】。值越大,找到的边缘越少
-
double类型的threshold2,第二个滞后性阈值【高阈值】。
-
int类型的apertureSize,表示应用Sobel算子的孔径大小,其有默认值3。
-
bool类型的L2gradient,一个计算图像梯度幅值的标识,有默认值false。
低于阈值1的像素点会被认为不是边缘;
高于阈值2的像素点会被认为是边缘;
在阈值1和阈值2之间的像素点,若与第2步得到的边缘像素点相邻,则被认为是边缘,否则被认为不是边缘。
//霍夫圆检测
void HoughCircles( CvArr* image, void* circle_storage, int method, double dp, double min_dist, double param1=100, double param2=100, int min_radius=0, int max_radius=0 );
- image:输入 8-比特、单通道灰度图像
- circle_storage:检测到的矩阵,3个参数为圆心坐标(x,y)和半径
- method:Hough 变换方式,目前只支持CV_HOUGH_GRADIENT
- dp:累加器图像的分辨率。这个参数允许创建一个比输入图像分辨率低的累加器。(这样做是因为有理由认为图像中存在的圆会自然降低到与图像宽高相同数量的范畴)。如果dp设置为1,则分辨率是相同的;如果设置为更大的值(比如2),累加器的分辨率受此影响会变小(此情况下为一半)。dp的值不能比1小。
- min_dist:该参数是让算法能明显区分的两个不同圆之间的最小距离。
- param1:用于Canny的边缘阀值上限,下限被置为上限的一半。
- param2:累加器的阀值。
- min_radius:最小圆半径。
- max_radius:最大圆半径。
//霍夫直线检测
void HoughLinesP(InputArray image, OutputArray lines, double rho, double theta, int threshold, double minLineLength=0, double maxLineGap=0 )
- image:8位的单通道二进制图像。
- lines:经过调用HoughLinesP函数后后存储了检测到的线条的输出矢量,每一条线由具有四个元素的矢量(x_1,y_1, x_2, y_2) 表示,其中,(x_1, y_1)和(x_2, y_2) 是是每个检测到的线段的端点。
- rho:以像素为单位的距离精度。另一种形容方式是直线搜索时的进步尺寸的单位半径。
- theta:以弧度为单位的角度精度。另一种形容方式是直线搜索时的进步尺寸的单位角度。
- threshold:累加平面的阈值参数,即识别某部分为图中的一条直线时它在累加平面中必须达到的值。大于阈值threshold的线段才可以被检测通过并返回到结果中。
- minLineLength:有默认值0,表示最低线段的长度,比这个设定参数短的线段就不能被显现出来。
- maxLineGap:有默认值0,允许将同一行点与点之间连接起来的最大的距离。
//找到两个平面之间的转换矩阵,返回值为矩阵。
Mat findHomography(InputArray srcPoints,InputArray dstPoints,int method = 0)
- srcPoints :源平面中点的坐标矩阵,可以是CV_32FC2类型,也可以是vector类型
- dstPoints :目标平面中点的坐标矩阵,可以是CV_32FC2类型,也可以是vector类型
- method :计算单应矩阵所使用的方法。不同的方法对应不同的参数,具体如下:0 - 利用所有点的常规方法,RANSAC - RANSAC-基于RANSAC的鲁棒算法,LMEDS - 最小中值鲁棒算法,RHO - PROSAC-基于PROSAC的鲁棒算法。
//透视变换
void warpPerspective(InputArray src, OutputArray dst, InputArray M, Size dsize, int flags=INTER_LINEAR)
- src:输入的图像
- dst:输出的图像
- M:透视变换的矩阵
- dsize:输出图像的大小
- INTER_LINEAR:输出图像的插值方法
如果知道输出图像的四点坐标,也可以调用GetPerspectiveTransform
//由四对点计算透射变换
perspectiveTransform(vector obj_corners1(4), vector scene_corners1(4), InputArray M)
- obj_corners1(4):模板图角点坐标。
- scene_corners1(4):待测图角点坐标
- M:转换矩阵
准备
因为不论是霍夫圆还是霍夫直线检测,都要先进行边缘提取,那么就涉及到一个参数选择问题,为了更好的选择参数,我们利用如下的参数选取代码,来确定得到最佳边缘分割的参数。
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/imgproc/types_c.h>
using namespace std;
using namespace cv;
// Define the Mat parameters
Mat g_srcImage, g_dstImage, g_midImage;
// Define a vector to collect all detected lines
vector<Vec4i> g_lines;
int g_nthreshold = 100;
static void showImage1(int, void*);
static void showImage2(int, void*);
int thred1 = 23;
int thred2 = 55;
// 23 55
int main()
{
// Load origin image
g_srcImage = imread("2.jpg");
// Show origin image
namedWindow("Dst Image", 1);
imshow("Origin Image", g_srcImage);
// Create a Tracebar
createTrackbar("threshold1", "Dst Image", &thred1, 500, showImage1);
createTrackbar("threshold2", "Dst Image", &thred2, 500, showImage2);
// Canny Detect and Gray am image
Canny(g_srcImage, g_midImage, thred1, thred2, 3);
cvtColor(g_midImage, g_dstImage, CV_GRAY2BGR);
showImage1(thred1, 0);
showImage2(thred2, 0);
// Show the dst image
imshow("Dst Image", g_dstImage);
waitKey(0);
return 0;
}
static void showImage1(int thred1, void*) {
// Canny Detection
Canny(g_srcImage, g_midImage, thred1, thred2, 3);
imshow("Dst Image", g_midImage);
}
static void showImage2(int thred2, void*)