第十一节 特征检测

OpenCV的imgproc模块提供了图像特征检测函数,包括Canny边缘检测、直线检测、角点检测等。

1、cv::Canny


使用Canny算法对输入图像进行边缘检测。

void cv::Canny(InputArray image,OutputArray edges,double threshold1,double threshold2,int apertureSize = 3,bool L2gradient = false)

该函数使用Canny算法在输入图像中找到边缘,并在输出地图边缘中对其进行标记。 threshold1和threshold2之间的最小值用于边缘链接。 最大值用于查找强边的初始段。 参见http://en.wikipedia.org/wiki/Canny_edge_detector

参数名称

参数描述

image

8位输入图像。

edges

输出边缘图; 单通道8位图像,其大小与image相同。

threshold1

第一个阈值

threshold2

第二个阈值

apertureSize

Sobel操作员的光圈尺寸。

L2gradient

标志,指示是否使用更加准确的CHECKERBOARD opencv 尺寸 opencv 尺寸测量_特征向量规范化CHECKERBOARD opencv 尺寸 opencv 尺寸测量_特征向量_02应该用于计算图像梯度幅度,或者使用默认的$L_1==

#include <iostream>
#include <opencv2/opencv.hpp>

using namespace std;

int main()
{
    // 读取图像
    cv::Mat src = cv::imread("images/lena.png");
    if(src.empty()){
        cerr << "cannot read image.\n";
        return EXIT_FAILURE;
    }

    // 转换成灰度图像
    cv::Mat gray;
    cv::cvtColor(src,gray,cv::COLOR_BGR2GRAY);

    // 计算Canny边缘
    cv::Mat edges;
    cv::Canny(gray,edges,128,255);

    // 显示图像
    cv::imshow("src",src);
    cv::imshow("dst",edges);

    cv::waitKey();
    cv::destroyAllWindows();

    return 0;
}

CHECKERBOARD opencv 尺寸 opencv 尺寸测量_边缘检测_03

其他重载形式函数如下:

  • void cv::Canny(InputArray dx,InputArray dy,OutputArray edges,double threshold1,double threshold2,bool L2gradient = false):通过图像梯度查找边缘。

2、cv::cornerEigenValsAndVecs、cv::cornerMinEigenVal


1)cv::cornerEigenValsAndVecs:计算图像块的特征值和特征向量以进行角点检测。

void cv::cornerEigenValsAndVecs(InputArray src,OutputArray dst,int blockSize,int ksize,int borderType = BORDER_DEFAULT)

对于每个像素CHECKERBOARD opencv 尺寸 opencv 尺寸测量_特征值_04,函数cornerEigenValsAndVecs考虑一个CHECKERBOARD opencv 尺寸 opencv 尺寸测量_边缘检测_05邻域CHECKERBOARD opencv 尺寸 opencv 尺寸测量_特征向量_06。 它将邻域上的导数的协方差矩阵计算为:

CHECKERBOARD opencv 尺寸 opencv 尺寸测量_特征向量_07

其中的导数是使用Sobel运算符计算的。

然后,它找到CHECKERBOARD opencv 尺寸 opencv 尺寸测量_特征值_08的特征向量和特征值,并将它们存储在目标图像中为CHECKERBOARD opencv 尺寸 opencv 尺寸测量_边缘检测_09其中:

  • CHECKERBOARD opencv 尺寸 opencv 尺寸测量_边缘检测_10是M的非排序特征值
  • CHECKERBOARD opencv 尺寸 opencv 尺寸测量_特征向量_11是对应于CHECKERBOARD opencv 尺寸 opencv 尺寸测量_特征值_12的特征向量
  • CHECKERBOARD opencv 尺寸 opencv 尺寸测量_边缘检测_13是对应于CHECKERBOARD opencv 尺寸 opencv 尺寸测量_特征值_12的特征向量

该函数的输出可用于鲁棒的边缘或拐角检测。参数如下:

参数名称

参数描述

src

输入单通道8位或浮点图像。

dst

用于存储结果的图像。 它具有与src相同的大小,并且类型为 CV_32FC(6)

blockSize

邻域规模(请参阅下面的详细信息)。

ksize

Sobel运算符的光圈参数。

borderType

像素外推法. 请参考BorderTypes。不支持 BORDER_WRAP 类型

#include <iostream>
#include <opencv2/opencv.hpp>

using namespace std;

int main()
{
    // 读取图像
    cv::Mat src = cv::imread("images/leaf.jpg");
    if(src.empty()){
        cerr << "cannot read image.\n";
        return EXIT_FAILURE;
    }

    // 转换成灰度图像
    cv::Mat gray;
    cv::cvtColor(src,gray,cv::COLOR_BGR2GRAY);

    // 计算特征值
    cv::Mat dst;
    int blockSize = 4,kernlSize = 5;
    cv::cornerEigenValsAndVecs(gray,dst,blockSize,kernlSize);

    cout << dst.at<cv::Vec6f>(0,0) << endl;

    return 0;
}

2)cv::cornerMinEigenVal:计算用于角点检测的梯度矩阵的最小特征值。

void cv::cornerMinEigenVal(InputArray src,OutputArray dst,int blockSize,int ksize = 3,int borderType = BORDER_DEFAULT)

该函数类似于cornerEigenValsAndVecs,但是它只计算和存储导数协方差矩阵的最小特征值,即cornerEigenValsAndVecs描述中的公式的CHECKERBOARD opencv 尺寸 opencv 尺寸测量_特征向量_15

参数名称

参数列表

src

输入单通道8位或浮点图像。

dst

用于存储最小特征值的图像。 它的类型为CV_32FC1,大小与src相同。

blockSize

邻域大小 (请参考 cornerEigenValsAndVecs )。

ksize

Sobel运算符的光圈参数。

borderType

像素外推法. 请参考BorderTypes。不支持 BORDER_WRAP 类型

3、cv::cornerHarris


哈里斯(Harris)角点检测。

void cv::cornerHarris(InputArray src,OutputArray dst,int blockSize,int ksize,double k,int borderType = BORDER_DEFAULT)

该函数对输入图像运行哈里斯角检测,类似于cornerMinEigenVal和cornerEigenValsAndVecs,对于每个像素CHECKERBOARD opencv 尺寸 opencv 尺寸测量_特征向量_16,它在CHECKERBOARD opencv 尺寸 opencv 尺寸测量_边缘检测_05邻域上计算CHECKERBOARD opencv 尺寸 opencv 尺寸测量_特征向量_18梯度协方差矩阵CHECKERBOARD opencv 尺寸 opencv 尺寸测量_特征值_19。 然后,它计算出以下特征:

CHECKERBOARD opencv 尺寸 opencv 尺寸测量_特征值_20

输入图像中的角点可以为该响应图的局部最大值。参数如下:

参数名称

参数描述

src

输入单通道8位或浮点图像。

dst

用于存储哈里斯探测器响应的图像。 它的类型为CV_32FC1,大小与src相同。

blockSize

邻域大小 (具体请参考 cornerEigenValsAndVecs ).

ksize

Sobel运算符的光圈参数。

k

哈里斯探测器自由参数。 请参阅上面的公式。

borderType

像素外推法。 请参考BorderTypes.。BORDER_WRAP 不支持。

#include <iostream>
#include <opencv2/opencv.hpp>

using namespace std;

int main()
{
    // 读取图像
    cv::Mat src = cv::imread("images/chessboard.png");
    if(src.empty()){
        cerr << "cannot read image.\n";
        return EXIT_FAILURE;
    }
    cv::Mat srcResized;
    cv::resize(src,srcResized,cv::Size(src.cols/6,src.rows/6));

    // 转换成灰度图
    cv::Mat gray;
    cv::cvtColor(srcResized,gray,cv::COLOR_BGR2GRAY);

    // 计算角点
    cv::Mat gray32f,dst;
    gray.convertTo(gray32f,CV_32FC1);
    // 最后一个参数在 0.04 到 0.05 之间
    cv::cornerHarris(gray32f,dst,2,5,0.04);

    cv::dilate(dst,dst,cv::Mat());

    // 阈值分割
    cv::threshold(dst,dst, 200,255,cv::THRESH_BINARY);

    // 归范化
    cv::Mat dstNorm,dstNormScaled;
    cv::normalize(dst,dstNorm,0,255,cv::NORM_MINMAX, CV_32FC1, cv::Mat());
    cv::convertScaleAbs( dstNorm, dstNormScaled );


    // 绘制角点
    cv::Mat dstDrawing = srcResized.clone();
    for( int j = 0; j < dstNorm.rows ; j++ )
    { for( int i = 0; i < dstNorm.cols; i++ )
        {
            if( (int) dstNorm.at<float>(j,i) >= 200 )
            {
                cv::drawMarker(dstDrawing,cv::Point(i,j),cv::Scalar(0,0,255),cv::MARKER_CROSS,20,1);
            }
        }
    }

    cv::imshow("dst",dstDrawing);
    cv::imshow("src",srcResized);

    cv::waitKey();


    return 0;
}

CHECKERBOARD opencv 尺寸 opencv 尺寸测量_边缘检测_21

4、cv::goodFeaturesToTrack


确定图像上的强角。

void cv::goodFeaturesToTrack(InputArray image,OutputArray corners,int maxCorners,double qualityLevel,double minDistance,InputArray mask = noArray(),int blockSize = 3,bool useHarrisDetector = false,double k = 0.04)

该函数可以找到图像中或指定图像区域中最突出的角,如[Jianbo Shi and Carlo Tomasi. Good features to track. In Computer Vision and Pattern Recognition, 1994. Proceedings CVPR’94., 1994 IEEE Computer Society Conference on, pages 593–600. IEEE, 1994.]中所述。

  • 函数使用cornerMinEigenVal或cornerHarris计算每个源图像像素的拐角质量度量。
  • 函数执行非最大值抑制(保留3 x 3邻域中的局部最大值)。
  • 最小特征值小于CHECKERBOARD opencv 尺寸 opencv 尺寸测量_特征向量_22的角点将被拒绝。
  • 其余的角点按质量度量按降序排序。
  • 函数会丢弃距离小于maxDistance的拐角处较强的每个角点。

注意:如果使用参数qualityLevel参数的不同值A和B以及A> B调用函数,则返回带有qualityLevel = A的角的向量将是带有qualityLevel = B的输出向量的前缀。

参数如下:

参数名称

参数描述

image

输入8位或浮点32位单通道图像。

corners

检测到的角的输出向量。

maxCorners

返回的最大角数。 如果角落多于找到的角落,则返回最强的角落。 “ maxCorners <= 0”表示没有设置最大值限制,并且返回了所有检测到的角。

qualityLevel

表征图像角的最低可接受质量的参数。 参数值乘以最佳拐角质量度量,即最小特征值(请参阅cornerMinEigenVal或 哈里斯函数响应(请参阅cornerHarris。 质量度量低于产品的角被拒绝。 例如,如果最佳角的质量量度= 1500,而qualityLevel = 0.01,则拒绝质量量度小于15的所有角。

minDistance

返回的角之间的最小可能欧几里得距离。

mask

可选的感兴趣区域。 如果图像不为空(它的类型必须为CV_8UC1且大小与image相同),则它指定检测到拐角的区域。

blockSize

用于计算每个像素邻域上的导数协方差矩阵的平均块的大小。 参见cornerEigenValsAndVecs。

useHarrisDetector

指示是否使用哈里斯探测器的参数(请参见cornerHarris或[cornerMinEigenVal](https:// docs.opencv.org/4.5.1/dd/d1a/group__imgproc__feature.html#ga3dbce297c1feb859ee36707e1003e0a8)

k

哈里斯(Harris)角点探测器的自由参数。

#include<opencv2/opencv.hpp>
#include<iostream>
#include<string>
#include<vector>
using namespace std;
using namespace cv;
Mat src, cornerImg, grayImg;
int mxCorners = 10;
RNG rngs = { 12345 };


int main() {
    // 读取图像
    cv::Mat src = cv::imread("images/chessboard.png", cv::IMREAD_COLOR);
    if(src.empty()){
        cerr << "cannot read image.\n";
        return EXIT_FAILURE;
    }
    cv::Mat image_color;
    cv::resize(src,image_color,cv::Size(src.rows / 6,src.cols/6));

    cv::Mat image_copy = image_color.clone();
    // 转换成灰度图像
    cv::Mat image_gray;
    cv::cvtColor(image_color, image_gray, cv::COLOR_BGR2GRAY);

    // 设置触点检测参数
    std::vector<cv::Point2f> corners;
    int max_corners = 100;
    double quality_level = 0.01;
    double min_distance = 10;
    int block_size = 3;
    bool use_harris = false;
    double k = 0.04;

    // 触点检测
    cv::goodFeaturesToTrack(image_gray,
                            corners,
                            max_corners,
                            quality_level,
                            min_distance,
                            cv::Mat(),
                            block_size,
                            use_harris,
                            k);

    // 绘制触点
    for (int i = 0; i < corners.size(); i++)
    {
        cv::circle(image_color, corners[i], 5, cv::Scalar(0, 0, 255), 2, 8, 0);
    }

    cv::imshow("corner", image_color);

    cv::waitKey(0);
}

CHECKERBOARD opencv 尺寸 opencv 尺寸测量_特征向量_23

其他重载函数形式:

  • void cv::goodFeaturesToTrack(InputArray image,OutputArray corners,int maxCorners,double qualityLevel,double minDistance,InputArray mask,int blockSize,int gradientSize,bool useHarrisDetector = false,double k = 0.04)

5、cv::cornerSubPix


细化角点位置。

void cv::cornerSubPix(InputArray image,InputOutputArray corners,Size winSize,Size zeroZone,TermCriteria criteria)

该函数会反复进行迭代,以找到[W FORSTNER. A fast operator for detection and precise location of distincs points, corners and center of circular features. In Proc. of the Intercommission Conference on Fast Processing of Photogrammetric Data, Interlaken, Switzerland, 1987, pages 281–305, 1987.]中所述的拐角或径向鞍点的子像素准确位置,如下图所示:

CHECKERBOARD opencv 尺寸 opencv 尺寸测量_边缘检测_24

亚像素精确角定位器基于以下观察结果:从中心CHECKERBOARD opencv 尺寸 opencv 尺寸测量_边缘检测_25到位于CHECKERBOARD opencv 尺寸 opencv 尺寸测量_边缘检测_25附近的点CHECKERBOARD opencv 尺寸 opencv 尺寸测量_特征值_04的每个矢量都正交于CHECKERBOARD opencv 尺寸 opencv 尺寸测量_特征值_04处受图像和测量噪声影响的图像梯度。考虑以下表达式:

CHECKERBOARD opencv 尺寸 opencv 尺寸测量_特征值_29

其中CHECKERBOARD opencv 尺寸 opencv 尺寸测量_特征值_30CHECKERBOARD opencv 尺寸 opencv 尺寸测量_边缘检测_25附近的点CHECKERBOARD opencv 尺寸 opencv 尺寸测量_边缘检测_32之一上的图像梯度。将找到CHECKERBOARD opencv 尺寸 opencv 尺寸测量_边缘检测_25的值,以使CHECKERBOARD opencv 尺寸 opencv 尺寸测量_特征值_34最小。 可以将CHECKERBOARD opencv 尺寸 opencv 尺寸测量_特征值_34设置为零来建立方程组:

CHECKERBOARD opencv 尺寸 opencv 尺寸测量_特征向量_36

梯度在CHECKERBOARD opencv 尺寸 opencv 尺寸测量_边缘检测_25的邻域(“搜索窗口”)内求和。 将第一梯度项CHECKERBOARD opencv 尺寸 opencv 尺寸测量_边缘检测_38和第二梯度项CHECKERBOARD opencv 尺寸 opencv 尺寸测量_边缘检测_39称为:CHECKERBOARD opencv 尺寸 opencv 尺寸测量_特征值_40

该算法将邻域窗口的中心设置在此新中心CHECKERBOARD opencv 尺寸 opencv 尺寸测量_边缘检测_25处,然后进行迭代,直到中心保持在设置的阈值内。参数如下:

参数名称

参数描述

image

输入单通道,8位或浮点图像。

corners

输入角的初始坐标和提供给输出的精确坐标。

winSize

搜索窗口边长的一半。比如, 如果 winSize=Size(5,5) , 则 搜索窗口大小为(5∗2+1)×(5∗2+1)=11×11

zeroZone

搜索区域中间的盲区大小的一半,未完成以下公式中的求和。 有时使用它来避免自相关矩阵可能的奇异性。 值(-1,-1)表示没有这样的大小。

criteria

终止角点优化迭代过程的条件。 也就是说,角点位置细化的过程在criteria.maxCount迭代之后或在某个迭代中拐角位置移动小于criteria.epsilon时停止。

#include<opencv2/opencv.hpp>
#include<iostream>
#include<string>
#include<vector>
using namespace std;
using namespace cv;
Mat src, cornerImg, grayImg;
int mxCorners = 10;
RNG rngs = { 12345 };


int main() {
    // 读取图像
    cv::Mat src = cv::imread("images/chessboard.png", cv::IMREAD_COLOR);
    if(src.empty()){
        cerr << "cannot read image.\n";
        return EXIT_FAILURE;
    }
    cv::Mat image_color;
    cv::resize(src,image_color,cv::Size(src.rows / 6,src.cols/6));

    cv::Mat image_copy = image_color.clone();
    // 转换成灰度图像
    cv::Mat image_gray;
    cv::cvtColor(image_color, image_gray, cv::COLOR_BGR2GRAY);

    // 设置触点检测参数
    std::vector<cv::Point2f> corners;
    int max_corners = 100;
    double quality_level = 0.01;
    double min_distance = 10;
    int block_size = 3;
    bool use_harris = false;
    double k = 0.04;

    // 触点检测
    cv::goodFeaturesToTrack(image_gray,
                            corners,
                            max_corners,
                            quality_level,
                            min_distance,
                            cv::Mat(),
                            block_size,
                            use_harris,
                            k);

    // 绘制触点
    for (int i = 0; i < corners.size(); i++)
    {
        cv::circle(image_color, corners[i], 5, cv::Scalar(0, 0, 255), 2, 8, 0);
    }

    // 计算迭代
    cv::TermCriteria criteria = cv::TermCriteria(
                cv::TermCriteria::MAX_ITER + cv::TermCriteria::EPS,
                40,
                0.01);

    //来像素触点检测
    cv::cornerSubPix(image_gray, corners, cv::Size(5, 5), cv::Size(-1, -1), criteria);

    //绘制触点
    for (int i = 0; i < corners.size(); i++)
    {
        cv::circle(image_copy, corners[i], 5, cv::Scalar(0, 255, 0), 2, 8, 0);
    }

    cv::imshow("corner", image_color);
    cv::imshow("sub pixel corner", image_copy);

    cv::imwrite("corner.jpg", image_color);
    cv::imwrite("corner_sub.jpg", image_copy);
    cv::waitKey(0);
}

CHECKERBOARD opencv 尺寸 opencv 尺寸测量_特征向量_42

6、cv::HoughCircles


使用霍夫变换在灰度图像中查找圆。

void cv::HoughCircles(InputArray image,OutputArray circles,int method,double dp,double minDist,double param1 = 100,double param2 = 100,int minRadius = 0,int maxRadius = 0)

该函数使用霍夫变换的修改来找到灰度图像中的圆。

注意:通常该函数可以很好地检测圆心。但是,它可能找不到正确的半径。 您可以通过指定半径范围(minRadius和maxRadius)来辅助该功能(如果您知道的话)。或者,对于HOUGH_GRADIENT方法,可以将maxRadius设置为负数,以便仅返回中心而不进行半径搜索,并使用其他过程查找正确的半径。

除非图像已经很柔和,否则还可以使图像稍微平滑一些。 例如,具有7x7内核和1.5x1.5 sigma或类似模糊效果的GaussianBlur()可能会有所帮助。

参数如下:

参数名称

参数描述

image

8位单通道灰度输入图像。

circles

找到的圆的输出向量。 每个向量被编码为3或4个元素浮点向量(x,y,radius)或(x,y,radius,votes)。

method

检测方法, 请参考 HoughModes. 有效的方法为 HOUGH_GRADIENTHOUGH_GRADIENT_ALT

dp

累加器分辨率与图像分辨率的反比。 例如,如果dp = 1,则累加器具有与输入图像相同的分辨率。 如果dp = 2,则累加器的宽度和高度是其一半。 对于HOUGH_GRADIENT_ALT的建议值是dp = 1.5,除非需要很小。

minDist

检测到的圆心之间的最小距离。 如果参数太小,除了真实的圆圈外,还可能会错误地检测到多个邻居圆圈。 如果太大,可能会错过一些圆圈。

param1

第一个方法特定的参数。 如果是HOUGH_GRADIENT,它是传递给Canny边缘检测器的两个阈值中的较高阈值(较低的阈值是较小的两倍)。 请注意HOUGH_GRADIENT_ALT使用的是Scharr算法来计算图像导数,因此阈值通常较高,例如300或正常曝光和对比图像。

param2

第二种方法特定的参数。 如果是HOUGH_GRADIENT,则是检测到的圆心的累加器阈值。 它越小,可能会检测到更多的假圆圈。 与较大的累加器值相对应的圆将首先返回。 对于HOUGH_GRADIENT_ALT算法,此圆为“完美”。 它越接近1,则选择的形状更好的圆形算法。 在大多数情况下,0.9应该可以。 如果要更好地检测小圆圈,可以将其降低到0.85、0.8甚至更低。 但是,然后还要尝试限制搜索范围[minRadius,maxRadius],以避免出现许多错误的圆圈。

minRadius

最小圆半径。

maxRadius

最大圆半径. If <= 0,使用最大图像尺寸. If < 0, HOUGH_GRADIENT 返回中心但未找到半径. HOUGH_GRADIENT_ALT始终计算圆半径。

#include <iostream>
#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;

int main()
{
    Mat img, gray;
    img = cv::imread("images/coints.jpg");
    cvtColor(img, gray, COLOR_BGR2GRAY);
    // 平滑图像
    GaussianBlur( gray, gray, Size(9, 9), 2, 2 );
    vector<Vec3f> circles;
    // 查找圆
    HoughCircles(gray, circles, HOUGH_GRADIENT,
                 2, gray.rows/4, 200, 100 );
    // 绘制圆
    for( size_t i = 0; i < circles.size(); i++ )
    {
        Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
        int radius = cvRound(circles[i][2]);
        // 绘制圆心
        circle( img, center, 3, Scalar(0,255,0), -1, 8, 0 );
        // 绘制圆轮廓
        circle( img, center, radius, Scalar(0,0,255), 3, 8, 0 );
    }
    namedWindow( "circles", 1 );
    imshow( "circles", img );
    waitKey(0);
    return 0;
}

CHECKERBOARD opencv 尺寸 opencv 尺寸测量_特征值_43

7、cv::HoughLines、cv::HoughLinesP


1)cv::HoughLines:使用标准霍夫变换在二进制图像中查找线。

void cv::HoughLines (InputArray image,OutputArray lines,double rho,double theta,int threshold,double srn = 0,double stn = 0,double min_theta = 0,double max_theta = CV_PI)

该函数实现用于线检测的标准或标准多尺度霍夫变换算法。有关霍夫变换的详细说明,请参见http://homepages.inf.ed.ac.uk/rbf/HIPR2/hough.htm。参数如下:

参数名称

参数描述

image

8位单通道二进制源图像。 该图像可以通过该功能进行修改。

lines

线的输出向量。 每条线由2或3个元素向量(ρ,θ)或(ρ,θ,votes)表示。 ρ是距坐标原点(0,0)(图像的左上角)的距离。 θ是弧度的线旋转角(0〜垂直线,π/ 2〜水平线)。 票数是累加器的价值。

rho

累加器的距离分辨率(以像素为单位)。

theta

累加器的角度分辨率(以弧度为单位)。

threshold

Accumulator阈值参数。 仅返回获得足够投票的那些行(> threshold)。

srn

对于多尺度霍夫变换,它是距离分辨率rho的除数。 粗略的累加器距离分辨率为rho,准确的累加器分辨率为rho / srn。 如果srn = 0和stn = 0都使用经典的Hough变换。 否则,这两个参数都应为正。

stn

对于多尺度霍夫变换,它是距离分辨率θ的除数。

min_theta

对于标准和多尺度霍夫变换,请使用最小角度检查线条。 必须介于0和max_theta之间。

max_theta

对于标准和多尺度霍夫变换,请使用最大角度来检查线条。 必须介于min_theta和CV_PI之间。

2)cv::HoughLinesP:使用概率霍夫变换在二进制图像中查找线段。

该函数实现了用于行检测的概率霍夫变换算法,在[Jiri Matas, Charles Galambos, and Josef Kittler. Robust detection of lines using the progressive probabilistic hough transform. Computer Vision and Image Understanding, 78(1):119–137, 2000.]中进行了描述。参数如下:

参数名称

参数描述

image

8位单通道二进制源图像。 该图像可以通过该功能进行修改。

lines

线的输出向量。 每条线由一个4元素向量(x1,y1,x2,y2)表示,其中(x1,y1)和(x2,y2)是每个检测到的线段的终点。

rho

累加器的距离分辨率(以像素为单位)。

theta

累加器的角度分辨率(以弧度为单位)。

threshold

Accumulator阈值参数。 仅返回获得足够投票的那些行(> threshold)。

minLineLength

最小线长。 短于此的线段将被拒绝。

maxLineGap

连接同一条线上的点之间的最大允许间隙。

#include <iostream>
#include <opencv2/opencv.hpp>

using namespace cv;
using namespace std;

int main()
{
    // 定义输出变量
    Mat dst, cdst, cdstP;

    // 读取图像
    Mat src = imread("images/building-3.jpg", IMREAD_GRAYSCALE );
    if(src.empty()){
        cerr << "cannot open image.\n";
        return EXIT_FAILURE;
    }
    // 边缘检测
    Canny(src, dst, 180, 200, 3);
    // 转换图像颜色空间
    cvtColor(dst, cdst, COLOR_GRAY2BGR);
    cdstP = cdst.clone();
    // 标准Hough直线检测
    vector<Vec2f> lines; // will hold the results of the detection
    HoughLines(dst, lines, 1, CV_PI/180, 150, 0, 0 ); // runs the actual detection
    //绘制直线
    for( size_t i = 0; i < lines.size(); i++ )
    {
        float rho = lines[i][0], theta = lines[i][1];
        Point pt1, pt2;
        double a = cos(theta), b = sin(theta);
        double x0 = a*rho, y0 = b*rho;
        pt1.x = cvRound(x0 + 1000*(-b));
        pt1.y = cvRound(y0 + 1000*(a));
        pt2.x = cvRound(x0 - 1000*(-b));
        pt2.y = cvRound(y0 - 1000*(a));
        line( cdst, pt1, pt2, Scalar(0,0,255), 3, LINE_AA);
    }
    // 概率Hough直线检测
    vector<Vec4i> linesP;
    HoughLinesP(dst, linesP, 1, CV_PI/180, 50, 50, 10 );
    // 绘制直线
    for( size_t i = 0; i < linesP.size(); i++ )
    {
        Vec4i l = linesP[i];
        line( cdstP, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(0,0,255), 3, LINE_AA);
    }
    // 显示结果
    imshow("Source", src);
    imshow("Detected Lines (in red) - Standard Hough Line Transform", cdst);
    imshow("Detected Lines (in red) - Probabilistic Line Transform", cdstP);
    waitKey();
    return 0;
}

CHECKERBOARD opencv 尺寸 opencv 尺寸测量_特征值_44

8、cv::HoughLinesPointSet


使用标准霍夫变换在一组点中查找线。

void cv::HoughLinesPointSet(InputArray _point,OutputArray _lines,int lines_max,int threshold,double min_rho,double max_rho,double rho_step,double min_theta,double max_theta,double theta_step)

参数如下:

参数名称

参数描述

_point

点的输入向量。 每个向量都必须编码为点向量(x,y)。 类型必须为CV_32FC2或CV_32SC2。

_lines

找到的行的输出向量。 每个向量都被编码为vector (票数,rho,θ)。 “投票”的值越大,霍夫线的可靠性就越高。

lines_max

霍夫线的最大数量。

threshold

Accumulator阈值参数。 仅返回获得足够投票的那些行(> threshold)。

min_rho

累加器的最小距离值(以像素为单位)。

max_rho

累加器的最大距离值(以像素为单位)。

rho_step

累加器的距离分辨率(以像素为单位)。

min_theta

累加器的最小角度值(以弧度为单位)。

max_theta

累加器的最大角度值(以弧度为单位)。

theta_step

累加器的角度分辨率(以弧度为单位)。

#include <iostream>
#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;
int main()
{

    Mat lines;
    vector<Vec3d> line3d;
    vector<Point2f> point;
    const static float Points[20][2] = {
    { 0.0f,   369.0f }, { 10.0f,  364.0f }, { 20.0f,  358.0f }, { 30.0f,  352.0f },
    { 40.0f,  346.0f }, { 50.0f,  341.0f }, { 60.0f,  335.0f }, { 70.0f,  329.0f },
    { 80.0f,  323.0f }, { 90.0f,  318.0f }, { 100.0f, 312.0f }, { 110.0f, 306.0f },
    { 120.0f, 300.0f }, { 130.0f, 295.0f }, { 140.0f, 289.0f }, { 150.0f, 284.0f },
    { 160.0f, 277.0f }, { 170.0f, 271.0f }, { 180.0f, 266.0f }, { 190.0f, 260.0f }
    };
    for (int i = 0; i < 20; i++)
    {
        point.push_back(Point2f(Points[i][0],Points[i][1]));
    }
    double rhoMin = 0.0f, rhoMax = 360.0f, rhoStep = 1;
    double thetaMin = 0.0f, thetaMax = CV_PI / 2.0f, thetaStep = CV_PI / 180.0f;
    HoughLinesPointSet(point, lines, 20, 1,
                       rhoMin, rhoMax, rhoStep,
                       thetaMin, thetaMax, thetaStep);
    lines.copyTo(line3d);
    printf("votes:%d, rho:%.7f, theta:%.7f\n",(int)line3d.at(0).val[0], line3d.at(0).val[1], line3d.at(0).val[2]);
    return 0;
}

9、cv::preCornerDetect


计算用于拐角检测的特征图。

void cv::preCornerDetect(InputArray src,OutputArray dst,int ksize,int borderType = BORDER_DEFAULT)

该函数计算源图像的基于复杂空间导数的函数:

CHECKERBOARD opencv 尺寸 opencv 尺寸测量_特征向量_45

其中CHECKERBOARD opencv 尺寸 opencv 尺寸测量_边缘检测_46是第一图像导数,CHECKERBOARD opencv 尺寸 opencv 尺寸测量_特征值_47是第二图像导数,CHECKERBOARD opencv 尺寸 opencv 尺寸测量_边缘检测_48是混合导数。

参数如下:

参数名称

参数描述

src

输入单通道8位浮点图像。

dst

输出图像的类型为CV_32F,大小与src相同。

ksize

Sobel算子的光圈大小。

borderType

像素外推法. 请参考BorderTypes.。不支持BORDER_WRAP

#include<opencv2/opencv.hpp>
#include<iostream>
#include<string>
#include<vector>
using namespace std;
using namespace cv;
Mat src, cornerImg, grayImg;
int mxCorners = 10;
RNG rngs = { 12345 };


int main() {
    // 读取图像
    cv::Mat src = cv::imread("images/chessboard.png", cv::IMREAD_COLOR);
    if(src.empty()){
        cerr << "cannot read image.\n";
        return EXIT_FAILURE;
    }
    cv::Mat image_color;
    cv::resize(src,image_color,cv::Size(src.rows / 6,src.cols/6));

    cv::Mat image_copy = image_color.clone();
    // 转换成灰度图像
    cv::Mat image_gray,corners;
    cv::cvtColor(image_color, image_gray, cv::COLOR_BGR2GRAY);

    // 角点检测
//    cv::cornerHarris(image_gray,corners,4,5,0.04);
    cv::Mat dilated_corners;
    cv::preCornerDetect(image_gray, corners, 3);
    cv::dilate(corners, dilated_corners, cv::Mat());
    Mat corner_mask = (corners == dilated_corners);

    cv::imshow("corner", image_color);
    cv::imshow("corner-mask",corner_mask);

    cv::waitKey(0);
}

CHECKERBOARD opencv 尺寸 opencv 尺寸测量_特征值_49