Opencv(C++)笔记--计算图形矩

目录

1--图形矩的概念

2--OpenCV API

3--代码实例


1--图形矩的概念

        ① 几何矩:计算公式如下所示,其中(i + j)的和表示矩的阶数,当(i + j) = 2时称为二阶几何矩;

        M_{ji}=\sum_{x,y}^{}\left ( P\left (x,y \right ) \cdot x^{j} \cdot y^{i} \right )

        ② 中心距:计算公式如下所示,其中\bar{x},\bar{y}表示中心质点坐标;

Mu_{ji}=\sum_{x,y}^{}\left ( P\left (x,y \right ) \cdot (x - \bar{x})^{j} \cdot (y - \bar{y})^{i} \right )

        ③ 中心归一化矩:计算公式如下所示;

nu_{ji}=\frac{mu_{ji}}{m_{00}^{(i+j)/2+1}}

可以利用几何矩计算图像轮廓的中心,即质心位置(x_{0}, y_{0}),计算公式如下:

x_{0}=\frac{m_{10}}{m_{00}},y_{0}=\frac{m_{01}}{m_{00}}

2--OpenCV API

cv::Moments cv::moments(cv::InputArray array, bool binaryImage = false)

        在利用 Opencv 计算图形矩时,通常的作法是对源图像进行提取轮廓,对提取的轮廓分别计算图形矩;

        通过 Moments = cv::moments()计算图像矩,通过Moments.m00调用相应阶数的几何矩,具体可参考博客1

3--代码实例

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

int threshold_value = 100;
int threshold_max = 255;
cv::Mat src;
cv::Mat gray;
cv::RNG rng(12345);

void Demo_moments(int, void*){
    cv::Mat Canny_output;
    std::vector<std::vector<cv::Point>> contours;
    std::vector<cv::Vec4i> hierachy;

    cv::Canny(src, Canny_output, threshold_value, threshold_value*2, 3, false);
    cv::findContours(Canny_output, contours, hierachy, cv::RETR_TREE, cv::CHAIN_APPROX_SIMPLE, cv::Point(0, 0));

    std::vector<cv::Moments> contours_moments(contours.size());
    std::vector<cv::Point2f> ccs(contours.size());
    for(size_t i = 0; i < contours.size(); i++){
        contours_moments[i] = cv::moments(contours[i]); // 为每一个轮廓计算矩
        ccs[i] = cv::Point(static_cast<float>(contours_moments[i].m10 / contours_moments[i].m00), // 计算图像中心
                           static_cast<float>(contours_moments[i].m01 / contours_moments[i].m00));
    }

    cv::Mat drawImg;
    src.copyTo(drawImg);

    for(size_t i = 0; i < contours.size(); i++){
        cv::Scalar color = cv::Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255)); // 随机生成颜色

        // 输出每一个轮廓的中心坐标
        printf("center point x : %.2f y : %.2f \n", ccs[i].x, ccs[i].y);
        
        // 计算每一个轮廓的面积和弧长
        printf("contours %d area : %.2f   arc length : %2f\n", i, cv::contourArea(contours[i]), cv::arcLength(contours[i], true));
        cv::drawContours(drawImg, contours, i, color, 2, 8, hierachy, 0, cv::Point(0, 0));
        cv::circle(drawImg, ccs[i], 2, color, 2, 8);
    }
    cv::imshow("output", drawImg);
}

int main(int argc, char** argv){
    src = cv::imread("C:/Users/Liujinfu/Desktop/opencv_bilibili/test0101.jpg"); 
    if (src.empty()){
        printf("could not load image..\n");
        return -1;
    }
    cv::imshow("input", src);
    
    cv::cvtColor(src, gray, cv::COLOR_BGR2GRAY);
    cv::GaussianBlur(gray, gray, cv::Size(3, 3), 0, 0);

    cv::namedWindow("output");
    cv::createTrackbar("Threshold", "output", &threshold_value, threshold_max, Demo_moments);
    Demo_moments(0, 0);

    cv::waitKey(0);
    return 0;
}

         上图中,绿色点即为对应轮廓的质心位置。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值