【OpenCV图像处理】1.31 图形矩(Image Moments)

相关理论

几何矩

  • 几何矩 M j i = x , y ( P ( x , y ) x j y i ) M_{j i}=\sum_{x, y}\left(P(x, y) \cdot x^{j} \cdot y^{i}\right) ,其中(i+j)和等于几就叫做几阶距

  • 中心距 m u j i = x , y ( P ( x , y ) ( x x ˉ ) j ( y y ˉ ) i ) m u_{j i}=\sum_{x, y}\left(P(x, y) \cdot(x-\bar{x})^{j} \cdot(y-\bar{y})^{i}\right) ,其中 x ˉ , y ˉ \bar{x}, \bar{y} 表示它的中心质点。

  • 中心归一化距 n u j i = m u j i m 00 ( i + j ) / 2 + 1 \mathrm{nu}_{j i}=\frac{\mathrm{mu}_{j i}}{\mathrm{m}_{00}^{(i+j) / 2+1}}

  • 矩的概念介绍

    • 图像中心Center(x0,y0)
      x 0 = m 10 m 00 y 0 = m 01 m 00 \mathrm{x}_{0}=\frac{m_{10}}{m_{00}} y_{0}=\frac{m_{01}}{m_{00}}
  • API介绍与使用-计算矩cv::moments

moments(
    InputArray  array,//输入数据
    bool   binaryImage=false // 是否为二值图像
)

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

arcLength(
    InputArray  curve,//输入曲线数据
    bool   closed// 是否是封闭曲线
)

代码 & 效果展示

  • 演示代码 - 步骤
    • 提取图像边缘
    • 发现轮廓
    • 计算每个轮廓对象的矩
    • 计算每个对象的中心、弧长、面积

相关代码:

#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/imgproc/types_c.h>

using namespace std;
using namespace cv;

#ifndef P31
#define P31 31
#endif

#if P31 //图形矩形
Mat src, gray_src;
int threshold_value = 80;
int threshold_max = 255;
const char* output_win = "image moents demo";
RNG rng(12345);

void Demo_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++) {
        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) {
            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(output_win, drawImg);
    return;
}
#endif

int main() {
    std::string path = "../circle.JPG";
    cv::Mat img = cv::imread(path, 5);

    string str_input = "input image";
    string str_output = "output image";

    if (img.empty()) {
        std::cout << "open file failed" << std::endl;
        return -1;
    }

    namedWindow(str_input, WINDOW_AUTOSIZE);
    namedWindow(str_output, WINDOW_AUTOSIZE);
    imshow(str_input, img);

#if P31
    src = img;
    cvtColor(src, gray_src, CV_BGR2GRAY);
    GaussianBlur(gray_src, gray_src, Size(3, 3), 0, 0);

    char input_win[] = "input image";
    namedWindow(input_win, WINDOW_AUTOSIZE);
    namedWindow(output_win, WINDOW_AUTOSIZE);
    imshow(input_win, src);

    createTrackbar("Threshold Value : ", output_win, &threshold_value, threshold_max, Demo_Moments);
    Demo_Moments(0, 0);
#endif

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

展示效果:
在这里插入图片描述

发布了134 篇原创文章 · 获赞 30 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/donaldsy/article/details/103125314