OpenCV,均衡图像轮廓的直方图

3

我知道可以通过以下方式对图像的直方图进行均衡化:

equalizeHist(image, image);

如果我想定义一个感兴趣区域(roi),只需要对图像中的这个区域进行直方图均衡化:

Mat aux3 = image.clone();
equalizeHist(image(Rect(0,100, 200,200)), aux3(Rect(0,100, 200,200)));

我现在想做的事情(我不知道是否可能),是使用点向量(cv::vector contour)定义一个 Roi (轮廓)并均衡化此 Roi(此 Roi 不总是矩形)。因此,问题是:是否可以使用 OpenCV 函数来均衡化不是矩形的图像部分?
1个回答

5

OpenCV中没有内置函数可以使用掩码进行直方图均衡化。但您可以编写自定义函数。


获取灰度图像:

// Load image
Mat3b img = imread("path_to_image");

// Convert to grayscale
Mat1b gray;
cvtColor(img, gray, COLOR_BGR2GRAY);

在此输入图片描述

使用您的点来形成掩码:

// Your vector of points
vector<Point> pts = { Point(300, 180), Point(450, 150), Point(600, 200), Point(650, 350), Point(300,300) };

// Create the mask
Mat1b mask(img.rows, img.cols, uchar(0));
vector<vector<Point>> ptsarray{pts};
fillPoly(mask, ptsarray, Scalar(255));

enter image description here

调用自定义函数equalizeHistWithMask来使用掩膜均衡图像:

// Equalize with mask
Mat1b equalized;
equalizeHistWithMask(gray, equalized, mask);

这里输入图片描述

以下是完整代码,包括equalizeHistWithMask函数:

#include <iostream>
#include <vector>
#include <algorithm>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;

void equalizeHistWithMask(const Mat1b& src, Mat1b& dst, Mat1b mask = Mat1b())
{
    int cnz = countNonZero(mask);
    if (mask.empty() || ( cnz == src.rows*src.cols))
    {
        equalizeHist(src, dst);
        return;
    }

    dst = src.clone();

    // Histogram
    vector<int> hist(256,0);
    for (int r = 0; r < src.rows; ++r) {
        for (int c = 0; c < src.cols; ++c) {
            if (mask(r, c)) {
                hist[src(r, c)]++;
            }
        }
    }

    // Cumulative histogram
    float scale = 255.f / float(cnz);
    vector<uchar> lut(256);
    int sum = 0;
    for (int i = 0; i < hist.size(); ++i) {
        sum += hist[i];
        lut[i] = saturate_cast<uchar>(sum * scale);
    }

    // Apply equalization
    for (int r = 0; r < src.rows; ++r) {
        for (int c = 0; c < src.cols; ++c) {
            if (mask(r, c)) {
                dst(r, c) = lut[src(r,c)];
            }
        }
    }
}

int main()
{
    // Load image
    Mat3b img = imread("path_to_image");

    // Convert to grayscale
    Mat1b gray;
    cvtColor(img, gray, COLOR_BGR2GRAY);

    // Your vector of points
    vector<Point> pts = { Point(300, 180), Point(450, 150), Point(600, 200), Point(650, 350), Point(300,300) };

    // Create the mask
    Mat1b mask(img.rows, img.cols, uchar(0));
    vector<vector<Point>> ptsarray{pts};
    fillPoly(mask, ptsarray, Scalar(255));

    // Equalize with mask
    Mat1b equalized;
    equalizeHistWithMask(gray, equalized, mask);

    imshow("Gray", gray);
    imshow("Mask", mask);
    imshow("Equalized", equalized);
    waitKey();

    return 0;
}

致谢

本代码基于answers.opencv.org上的这个问题


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接