OpenCV基础API函数四

OpenCV基础API函数一

OpenCV基础API函数二

OpenCV基础API函数三

OpenCV基础API函数四

OpenCV基础API函数五

connectedComponents 联通组件扫描

int connectedComponents(InputArray image, OutputArray labels,int connectivity, int ltype, int ccltype);
返回值:轮廓的个数(包括图像本身轮廓)
image:输入的二值图像
labels:标记图像(同一个轮廓的编号一样)
connectivity: 4邻域算法或8邻域算法
ltype:输出结果图像的类型 CV_32S 或者CV_16U
ccltype:使用连接组件的算法

例如 :给轮廓图像填充颜色并输出轮廓的个数
在这里插入图片描述

void Demo::myConnectedComponents(Mat &src)
{
    Mat dst = Mat::zeros(src.size(), src.type());
    srand(time(NULL));

    //先把图像转化成灰度图像
    if (src.channels() >= 2)
    {
        cvtColor(src, src, COLOR_BGR2GRAY);
    }
    //在进行二值化之前进行稍微的模糊效果会更好
    GaussianBlur(src, dst, Size(0, 0), 3);
    namedWindow("模糊", WINDOW_FREERATIO);
    imshow("模糊", src);
    //二值化,联通组件需要背景是黑色
    threshold(src, src, 0, 255, THRESH_BINARY | cv::THRESH_OTSU);
    namedWindow("二值化", WINDOW_FREERATIO);
    imshow("二值化", src);
    //adaptiveThreshold(src, dst, 255, ADAPTIVE_THRESH_GAUSSIAN_C, THRESH_BINARY_INV, 11, 14);


    //获得联通组件的信息
    int labelCount = connectedComponents(src, dst, 8);
    cout << "边缘个数 " << labelCount - 1 << endl;
    //给边缘上色
    vector<Vec3b> colorLabel(labelCount - 1);
    colorLabel[0] = Vec3b(0, 0, 0);
    int row = src.rows;
    int col = src.cols;
    //生成随机颜色
    for (int i = 1; i < labelCount; ++i)
    {
        colorLabel[i] = Vec3b(rand() % 255, rand() % 255, rand() % 255);
    }
    Mat colorSrc = Mat::zeros(src.size(), CV_8UC3);
    //进行着色
    for (int i = 0; i < row; ++i)
    {
        for (int j = 0; j < col; ++j)
        {
            colorSrc.at<Vec3b>(i, j) = colorLabel[dst.at<int>(i, j)];
        }
    }
    putText(colorSrc, to_string(labelCount - 1), Point(50, 50), FONT_HERSHEY_PLAIN, 1.2, Scalar(0, 255, 255), 2);
    namedWindow("结果图像", WINDOW_FREERATIO);
    imshow("结果图像", colorSrc);

}

connectedComponentsWithStats 联通组件的统计信息

int connectedComponentsWithStats(InputArray image, OutputArray labels,
								OutputArray stats, OutputArray centroids,
								int connectivity, int ltype, int ccltype);
返回值:轮廓的个数(包括图像本身轮廓)
image:输入的二值图像
labels:标记图像(同一个轮廓的编号一样)
stats:统计信息,一共有五个值 前四个包括左上角的X,Y坐标 长和高,最后一个表示面积
centroids:轮廓的中心点
connectivity: 4邻域算法或8邻域算法
ltype:输出结果图像的类型 CV_32S 或者CV_16U
ccltype:使用连接组件的算法

例子:统计图像的轮廓个数,画出外界矩形
在这里插入图片描述

void Demo::myConnectStatistic(Mat &src){
    Mat labels, stats, centroids, dst;
    if(src.channels()>2)
    {
        cvtColor(src, dst, COLOR_BGR2GRAY);
    }

    labels = Mat::zeros(src.size(), CV_32S);
    stats = Mat::zeros(src.size(), CV_32S);
    centroids= Mat::zeros(src.size(), CV_32F);
    //在进行二值化之前进行稍微的模糊效果会更好
    GaussianBlur(dst, dst, Size(0, 0), 3);
    namedWindow("模糊", WINDOW_FREERATIO);
    imshow("模糊", dst);
    //二值化,联通组件需要背景是黑色
    threshold(dst, dst, 0, 255, THRESH_BINARY | cv::THRESH_OTSU);
    namedWindow("二值化", WINDOW_FREERATIO);
    imshow("二值化", dst);

    int labelCount = connectedComponentsWithStats(dst, labels, stats, centroids, 8, CV_32S, CCL_DEFAULT);

    for (int i = 1; i < labelCount; ++i)
    {
        //获得轮廓的中心
        double cx = centroids.at<double>(i, 0);
        double cy = centroids.at<double>(i, 1);
        //画出圆
        circle(src, Point(cx, cy), 10, Scalar(0, 0, 255), 2);

        //获得外接矩形
        int x = stats.at<int>(i, CC_STAT_LEFT);
        int y = stats.at<int>(i, CC_STAT_TOP);
        int h = stats.at<int>(i, CC_STAT_HEIGHT);
        int w = stats.at<int>(i, CC_STAT_WIDTH);
        //绘制外界矩形
        Rect rect(Point(x, y), Size(w, h));
        rectangle(src, rect, Scalar(0, 255, 0),2);
    }
    namedWindow("结果图像", WINDOW_FREERATIO);
    imshow("结果图像", src);

}

Moment HuMoment 集合矩与Hu矩

Moments moments( InputArray array, bool binaryImage = false );
返回值:Moments类型数据
array:输入图像 黑色背景的二值图像
binaryImage :输出的图像是否为二值图像
void HuMoments( const Moments& m, OutputArray hu );
返回值:空
m:几何矩
hu输出的结果 Hu矩

在这里插入图片描述
在这里插入图片描述

matchShapes 形状匹配

double matchShapes( InputArray contour1, InputArray contour2,
                                 int method, double parameter );
返回值:两个形状的相似度
contour1:Hu矩
contour2:Hu矩
method:计算两个Hu矩的方法
parmeter:目前还不支持 直接传入0

例子: 进行图像匹配
在这里插入图片描述

//发现轮廓信息 并传回轮廓信息
void findContour(Mat src, vector<vector<Point>> &contour)
{
    Mat dst;
    if (src.channels() >= 2)
    {
        cvtColor(src, dst, COLOR_BGR2GRAY);
    }
    //进行高斯模糊
    GaussianBlur(dst, dst, Size(3, 3), 0);
    //二值化
    threshold(dst, dst, 0, 255, THRESH_BINARY|THRESH_OTSU );
    vector<Vec4i> hierarchy;
    //发现图形轮廓
    findContours(dst, contour, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE, Point());

}

void myContourMatch(Mat &src, Mat &src1)
{
    //记录轮廓信息
    vector<vector<Point>> contour1;
    vector<vector<Point>> contour2;
    findContour(src, contour1);
    findContour(src1, contour2);

    //计算几何矩
    Moments mmt = moments(contour1[0], true);

    Mat hu1;
    //计算hu矩
    HuMoments(mmt, hu1);
    for (int i = 0; i < contour2.size(); ++i)
    {
        Mat hu2;
        HuMoments(moments(contour2[i], true), hu2);
        //计算两个Hu矩之差   图像匹配
        double dist= matchShapes(hu1,hu2,CONTOURS_MATCH_I1,0);
        cout << "图片的距离" << dist << endl;
        if(dist<1)
        {
            Rect box = boundingRect(contour2[i]);
            rectangle(src1, box, Scalar(0, 0, 255), 1);
        }
    }
    imshow("结果", src1);
}

HoughLines , HoughLinesP 霍夫直线检测

void 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 );
返回值:空
image: 二值化图像
line:输出点的集合
rho:以rho为单位的半径进行检测
thrta:以theta为单位的角度进行检测
threshold: 累计阈值参数
srn::对于多尺度的霍夫变换,这是第三个参数进步尺寸rho的除数距离
stn:对于多尺度的霍夫变换,srn表示第四个参数进步尺寸的单位角度theta的除数距离
void HoughLinesP( InputArray image, OutputArray lines,
                               double rho, double theta, int threshold,
                               double minLineLength = 0, double maxLineGap = 0 );
返回值:空
image:输入二值图像
lines:点的集合   类型为vector<Vec4f>
threshold:累加值,只有累加值达到threshold才认为是直线
minLineLength : 检测到的线段最小长度
maxLineGap :两条线段间隔大于 maxLineGap 认为是两条线段

例子:检测直线
在这里插入图片描述

void Demo::myHoughLines(Mat &src)
{
    Mat dst;
    if (src.channels() >= 2)
    {
        cvtColor(src, dst, COLOR_BGR2GRAY);
    }
    threshold(dst, dst, 0, 255, THRESH_OTSU | cv::THRESH_BINARY);
    namedWindow("二值", WINDOW_FREERATIO);
    imshow("二值", src);
    //记录点的信息 每一个lines有三个值都是浮点数类型
    //第一个代表rho半径
    //第二个代表theta角度
    //第三个代表累加值
    vector<Vec3f> lines;
    HoughLines(dst, lines, 1, CV_PI / 180, 100, 0, 0);
    for (int i = 0; i < lines.size(); ++i)
    {
        double rho = lines[i][0]; //半径 rho
        double theta = lines[i][1]; //角度
        double acc = lines[i][2];//累加值
        cout << "rho " << rho << " theta " << theta << " acc " << acc << endl;
        double cosX = cos(theta);
        double sinX = sin(theta);
        Point point1, point2;
        double x0=rho * cosX;
        double y0 = rho * sinX;
        point1.x = cvRound(x0 + 1000 * (-sinX));
        point1.y = cvRound(y0 + 1000 * ( cosX));
        point2.x = cvRound(x0 - 1000 * (-sinX));
        point2.y = cvRound(y0 - 1000 * ( cosX));
        double angle = round((theta / CV_PI) * 180);
        cout << "angle " << angle << endl;
        if (angle == 90)
        {//水平
            line(src, point1, point2, Scalar(0, 255, 0), 4);
        } else if (angle == 0)
        {//垂直
            line(src, point1, point2, Scalar(255, 0, 0), 4);
        } else
        {
            line(src, point1, point2, Scalar(0, 0, 255), 4);
        }
    }
    imshow("jieguo", src);


//HoughLinesP检测线段
 Mat dst;
    Canny(src, dst, 50, 80, 3);
    vector<Vec4f> lines;
    HoughLinesP(dst, lines, 1, CV_PI / 180, 100, 50, 30);
    Mat result = Mat::zeros(src.size(), src.type());
    for (int i = 0; i < lines.size(); ++i)
    {
        line(result, Point(lines[i][0], lines[i][1]), Point(lines[i][2], lines[i][3]), Scalar(0, 0, 255), 1);
    }
    imshow("结果", result);
}

HoughCircles 霍夫圆检测

void HoughCircles( InputArray image, OutputArray circles,
                               int method, double dp, double minDist,
                               double param1 = 100, double param2 = 100,
                               int minRadius = 0, int maxRadius = 0 );
返回值:空
image:输入图像 灰度图像
circles:输出的圆心和半径集合vector<Vec3f>   第一个和第二个为圆心坐标  第三个为半径
 dp:  提升这个值会使检测圆的能力大大大增强   为第一阶段所使用的霍夫空间的分辨率,dp=1时表示霍夫空间与输入图像空间的大小一致,dp=2时霍夫空间是输入图像空间的一半,以此类推;
 minDist:两个圆心之间的最小距离,这个值太小可能会检测出重复的圆,太大可能导致检测不到圆
 param1:Canny阈值的最大值  最小值为这个值得一半
 param2: 检测到圆的累加值  只有大于这个数的才算是圆
 minRadius:检测圆的最小半径
 maxRadius:检测圆的最大半径

例子:检测所有的圆
在这里插入图片描述

void myHoughCircle(Mat &src){

    Mat gray, dst;
    cvtColor(src, gray, COLOR_BGR2GRAY);
    vector<Vec3f> circles;

    HoughCircles(gray,circles,HOUGH_GRADIENT,1.4,10,100,100,10,50);
    for (int i = 0; i < circles.size(); ++i)
    {
        Point2f circleCenter(circles[i][0],circles[i][1]);
        double r = circles[i][2];
        circle(src, circleCenter, r, Scalar(0, 0, 255),2);
    }
    namedWindow("结果", WINDOW_FREERATIO);
    imshow("结果", src);
}

erode And dilate 腐蚀和膨胀

腐蚀API

void erode( InputArray src, OutputArray dst, InputArray kernel,
                         Point anchor = Point(-1,-1), int iterations = 1,
                         int borderType = BORDER_CONSTANT,
                         const Scalar& borderValue = morphologyDefaultBorderValue() );
返回值:空
src:输入二值图像 以黑色为背景的二值图像
dst:腐蚀过后的结果图像
kernel:结构元素
anchor:锚定点的中心位置
iterations :腐蚀重复的次数  建议用小窗口多次腐蚀  比用大窗口一次腐蚀效率更高
borderType :边缘填充的方式
borderValue :边缘的颜色

腐蚀是黑色侵蚀二值图像白色的面积
膨胀API

void dilate( InputArray src, OutputArray dst, InputArray kernel,
                          Point anchor = Point(-1,-1), int iterations = 1,
                          int borderType = BORDER_CONSTANT,
                          const Scalar& borderValue = morphologyDefaultBorderValue() );
返回值:空
src:输入的二值图像  以黑色为背景的二值图像
dst:膨胀过后的二值图像
kernel:结构元素
anchor:锚定点的中心位置
iterations :腐蚀重复的次数  建议用小窗口多次腐蚀  比用大窗口一次腐蚀效率更高
borderType :边缘填充的方式
borderValue :边缘的颜色

膨胀是扩张二值图像白色的面积

例子:消除图像中的噪声
在这里插入图片描述

void Demo::myErode(Mat &src)
{
    Mat dst;
    Mat binary;
    Mat result = Mat::ones(src.size(), src.type());
    result = Scalar(255, 255, 255);
    if (src.channels() >= 2)
    {
        cvtColor(src, dst, COLOR_BGR2GRAY);
    } else
    {
        dst = src.clone();
    }
    threshold(dst, binary, 0, 255, THRESH_BINARY_INV | cv::THRESH_OTSU);
    namedWindow("二值", WINDOW_FREERATIO);
    imshow("二值", binary);

    Mat kernel = getStructuringElement(MORPH_RECT, Size(3, 3), Point(-1, -1));

    erode(binary, dst, kernel, Point(-1, -1), 1, BORDER_DEFAULT);
    namedWindow("腐蚀", WINDOW_FREERATIO);
    imshow("腐蚀", dst);
    dilate(dst,dst,kernel,Point(-1,-1),1,BORDER_DEFAULT);
    namedWindow("膨胀", WINDOW_FREERATIO);
    imshow("膨胀", dst);

    src.copyTo(result, dst);

    namedWindow("结果", WINDOW_FREERATIO);
    imshow("结果", result);
}

形态学基本梯度,内梯度,外梯度

基本梯度:膨胀减去腐蚀之后的结果
内梯度:原图减去腐蚀之后的结果
外梯度:膨胀减去原图之后的结果

例子:形态学三种梯度
在这里插入图片描述
我们可以看出内梯度和外梯度提取边缘轮廓的效果更胜一筹

void Demo::morphologyOperation(Mat &src)
{
    Mat dst;
    Mat inside_gra, external_gra;
    Mat gray;

    if (src.channels() >= 2)
    {
        cvtColor(src, gray, COLOR_BGR2GRAY);
    } else
    {
        dst = src.clone();
    }
    Mat kernel = getStructuringElement(MORPH_RECT, Size(3, 3), Point(-1, -1));
    morphologyEx(gray, dst, MORPH_GRADIENT, kernel, Point(-1, -1));
    threshold(dst, dst, 0, 255, THRESH_BINARY|THRESH_OTSU);
    namedWindow("基本梯度", WINDOW_FREERATIO);
    imshow("基本梯度", dst);



//   内梯度

    erode(gray, inside_gra, kernel, Point(-1, -1), 1);
    subtract(gray, inside_gra, inside_gra);
    threshold(inside_gra, inside_gra, 0, 255, THRESH_BINARY|THRESH_OTSU);
    namedWindow("内梯度", WINDOW_FREERATIO);
    imshow("内梯度", inside_gra);


//外梯度
    dilate(gray, external_gra, kernel, Point(-1, -1), 1);
    subtract(external_gra, gray, external_gra);
    threshold(external_gra, external_gra, 0, 255, THRESH_BINARY|THRESH_OTSU);
    namedWindow("外梯度", WINDOW_FREERATIO);
    imshow("外梯度", inside_gra);

}

morphologyEx 形态学操作

void morphologyEx( InputArray src, OutputArray dst,
                                int op, InputArray kernel,
                                Point anchor = Point(-1,-1), int iterations = 1,
                                int borderType = BORDER_CONSTANT,
                                const Scalar& borderValue = morphologyDefaultBorderValue() );
返回值:空
dst:结果图像
op:形态学操作
kernel:结构元素
anchor:锚定点的中心
borderType:边缘填充类型
borderValue:边缘填充的颜色

op的类型

op意思
MORPH_ERODE腐蚀
MORPH_DILATE膨胀
MORPH_OPEN开操作
MORPH_CLOSE闭操作
MORPH_GRADIENT形态学梯度
MORPH_TOPHAT顶帽操作
MORPH_BLACKHAT黑帽操作
MORPH_HITMISS击中击不中操作
开操作: 消除白色小点 去除噪声(先腐蚀 后膨胀)
闭操作:扩大白色小点:填充空洞(先膨胀后腐蚀)
顶帽: 提取微小的噪声(原图减去开操作)
黑帽:提取微小的噪声(闭操作减去原图)
击中击不中:用来提取指定的形状(通过指定元素结构)

例子:黑帽
在这里插入图片描述

Mat dst;
    Mat inside_gra, external_gra;
    Mat gray;

    if (src.channels() >= 2)
    {
        cvtColor(src, gray, COLOR_BGR2GRAY);
    } else
    {
        dst = src.clone();
    }
    //Size越大提取的噪点越大
    threshold(gray, dst, 0, 255, THRESH_BINARY | THRESH_OTSU);
    Mat kernel = getStructuringElement(MORPH_ELLIPSE, Size(15, 15), Point(-1, -1));
    // 黑帽 顶帽  击中击不中 二值图像效果更好
    morphologyEx(dst, dst, MORPH_BLACKHAT, kernel, Point(-1, -1));
    namedWindow("黑帽", WINDOW_FREERATIO);
    imshow("黑帽", dst);

例子:顶帽
在这里插入图片描述

Mat dst;
    Mat inside_gra, external_gra;
    Mat gray;

    if (src.channels() >= 2)
    {
        cvtColor(src, gray, COLOR_BGR2GRAY);
    } else
    {
        dst = src.clone();
    }
    threshold(gray, dst, 0, 255, THRESH_BINARY | THRESH_OTSU);
    //Size越小提取的提取的噪点越小
    Mat kernel = getStructuringElement(MORPH_ELLIPSE, Size(3, 3), Point(-1, -1));
    // 黑帽 顶帽  击中击不中 二值图像效果更好
    morphologyEx(dst, dst, MORPH_TOPHAT, kernel, Point(-1, -1));
    namedWindow("顶帽", WINDOW_FREERATIO);
    imshow("顶帽", dst);

例子:击中击不中 提取十字结

在这里插入图片描述

Mat dst;
    Mat inside_gra, external_gra;
    Mat gray;

    if (src.channels() >= 2)
    {
        cvtColor(src, gray, COLOR_BGR2GRAY);
    } else
    {
        dst = src.clone();
    }
    threshold(gray, dst, 0, 255, THRESH_BINARY_INV | THRESH_OTSU);
    //Size越小提取的提取的噪点越小
    Mat kernel = getStructuringElement(MORPH_CROSS, Size(13, 13), Point(-1, -1));
    // 黑帽 顶帽  击中击不中 二值图像效果更好
    morphologyEx(dst, dst, MORPH_HITMISS, kernel, Point(-1, -1));
    namedWindow("击中击不中", WINDOW_FREERATIO);
    imshow("击中击不中", dst);
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

~搬~运~工~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值