OpenCV之图像处理(三十二) 图像矩(Image Moments)

矩:主要指几何矩  Mji = ∑ (P(x,y) · x^j · y^i)   其中 (i+j) 和等于几就是几阶矩,P(x,y)表示图像x,y坐标位置的像素值,i j 为变量
                       x,y
    还有中心矩(MUji), 中心归一化矩(NUji)  它们不考虑0阶,1阶?     

图像中心 Center(x0, y0)   x0 = M10 / M00 ,  y0 = M01 / M00   此非图像坐标的中心点,而是图像 质 的中心,质点

moments( // 计算矩,返回 0阶到3阶所有的几何矩,2阶到3阶所有的中心矩,2阶到3阶所有的中心归一矩
    InputArray  array, // 输入数据,findContours 找到的轮廓数据
    bool   binaryImage=false // 是否为二值图像
)

contourArea( // 求轮廓面积
    InputArray  contour, // 输入轮廓数据
    bool   oriented // 默认false、返回绝对值
)

arcLength( // 求轮廓弧长
    InputArray  curve, // 输入曲线数据
    bool   closed // 是否是封闭曲线
)

步骤:
    提取图像边缘
    发现轮廓
    计算每个轮廓对象的矩
    计算每个对象的中心、弧长、面积

代码

    #include "../common/common.hpp"

    static Mat src, gray_src;
    static int threshold_value = 80;
    static int threshold_max = 255;
    static const char* title = "moments";
    static RNG rng(12345);

    static void m_moments(int, void*);

    void main(int argc, char** argv)
    {
        src = imread(getCVImagesPath("images/circle.png"), IMREAD_COLOR);// redball.png
        imshow("src32", src);

        cvtColor(src, gray_src, CV_BGR2GRAY);
        GaussianBlur(gray_src, gray_src, Size(3, 3), 0, 0);//这里用高斯模糊去噪,相比于均值,轮廓发现的准确
        namedWindow(title, CV_WINDOW_AUTOSIZE);
        createTrackbar("rect round:", title, &threshold_value, threshold_max, m_moments);
        m_moments(0, 0);

        waitKey(0);
    }

    void m_moments(int, void*)
    {
        Mat canny_output;
        vector<vector<Point>> contours;
        vector<Vec4i> hierachy;

        Canny(gray_src, canny_output, threshold_value, threshold_value * 2, 3, false);//提取边缘
        findContours(canny_output, contours, hierachy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));//发现轮廓

        vector<Moments> contours_moments(contours.size());//存放各阶各种矩
        vector<Point2f> ccs(contours.size());//各阶各种矩的图像中心,质点
        for (size_t i = 0; i < contours.size(); i++) {
            //计算矩,返回 0阶到3阶所有的几何矩,2阶到3阶所有的中心矩,2阶到3阶所有的中心归一矩
            contours_moments[i] = moments(contours[i]);
            ccs[i] = Point(static_cast<float>(contours_moments[i].m10 / contours_moments[i].m00), 
                static_cast<float>(contours_moments[i].m01 / contours_moments[i].m00));//计算质点
        }

        Mat drawImg;// = Mat::zeros(src.size(), CV_8UC3);
        src.copyTo(drawImg);
        for (size_t i = 0; i < contours.size(); i++) {
            if (contours[i].size() < 100) { // 点数小于100的轮廓,忽略
                continue;
            }
            Scalar color = 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, contourArea(contours[i]), 
                arcLength(contours[i], true));
            drawContours(drawImg, contours, i, color, 2, 8, hierachy, 0, Point(0, 0));//绘制轮廓
            circle(drawImg, ccs[i], 2, color, 2, 8);//绘制质点
        }

        imshow(title, drawImg);
    }

效果图

这里写图片描述

猜你喜欢

转载自blog.csdn.net/huanghuangjin/article/details/81189586