C++实现Matlab imregionalmax函数——查找区域最大值

C++实现imregionalmax函数

  • [1 说明](#1 说明)
  • [2 示例](#2 示例)
  • [3 C++实现](#3 C++实现)

1 说明

Matlab imregionalmax

bash 复制代码
BW = imregionalmax(I)  

返回标识灰度图像 I 中区域最大值的二值图像BW。

区域最大值点是具有同一强度值的连通像素分量,其周围的像素强度值比该值低。

BW --- 逻辑数组

区域最大值的位置,以与 I 大小相同的逻辑数组形式返回。值为 1 的像素表示区域最大值;所有其他像素设置为 0。

2 示例

在简单示例图像中寻找区域最大值

创建一个具有若干区域最大值的简单示例图像。

bash 复制代码
A = 10*ones(10,10);
A(2:4,2:4) = 22; 
A(6:8,6:8) = 33; 
A(2,7) = 44;
A(3,8) = 45;
A(4,9) = 44
bash 复制代码
A = 10×10

    10    10    10    10    10    10    10    10    10    10
    10    22    22    22    10    10    44    10    10    10
    10    22    22    22    10    10    10    45    10    10
    10    22    22    22    10    10    10    10    44    10
    10    10    10    10    10    10    10    10    10    10
    10    10    10    10    10    33    33    33    10    10
    10    10    10    10    10    33    33    33    10    10
    10    10    10    10    10    33    33    33    10    10
    10    10    10    10    10    10    10    10    10    10
    10    10    10    10    10    10    10    10    10    10

查找区域最大值。请注意,结果包括在 (3,8) 处的区域最大值。

bash 复制代码
regmax = imregionalmax(A)
bash 复制代码
regmax = 10x10 logical array

   0   0   0   0   0   0   0   0   0   0
   0   1   1   1   0   0   0   0   0   0
   0   1   1   1   0   0   0   1   0   0
   0   1   1   1   0   0   0   0   0   0
   0   0   0   0   0   0   0   0   0   0
   0   0   0   0   0   1   1   1   0   0
   0   0   0   0   0   1   1   1   0   0
   0   0   0   0   0   1   1   1   0   0
   0   0   0   0   0   0   0   0   0   0
   0   0   0   0   0   0   0   0   0   0

3 C++实现

cpp 复制代码
namespace MatlabCppCode {

    bool isPeak(cv::Mat mx[], std::vector<cv::Point>& conn_points)
    {
        cv::Point poi_point = conn_points.back();
        int row = poi_point.y;
		int col = poi_point.x;
		float poi_val = mx[0].at<float>(poi_point);
		bool isPeakEle = true;
		for (int mask_row = row - 1; mask_row >= 0 && mask_row <= row + 1 && mask_row < mx[0].rows; mask_row++) {
			for (int mask_col = col - 1; mask_col >= 0 && mask_col <= col + 1 && mask_col < mx[0].cols; mask_col++) {

				if (mask_row == row && mask_col == col) {
					continue;
				}
				float conn_pt_val = mx[0].at<float>(mask_row, mask_col);
				if (poi_val < conn_pt_val) {
                    isPeakEle = false;
                    break;
                }
                if (poi_val == conn_pt_val) {
                    int Peak_status = mx[1].at<uchar>(mask_row, mask_col);
                    if (Peak_status == 0) {
                        isPeakEle = false;
                        break;
                    }
                    else if (Peak_status == 1) {
                        isPeakEle = true;
                        break;
                    }
                    else {
                        cv::Point p(mask_col, mask_row);
                        std::vector<cv::Point>::iterator it;
                        it = std::find(conn_points.begin(), conn_points.end(), p);
                        if (it == conn_points.end()) {
                            conn_points.push_back(p);
                            isPeakEle = isPeakEle && isPeak(mx, conn_points);
                        }
                    }
                }
            }
            if (isPeakEle == false) {
                break;
            }
        }
        return isPeakEle;
    }

    /**
     * @brief This is equivalent to imregionalmax(img, conn = 8) of Matlab
     * It takes floating point matrix, finds all local maximas and put them in 8UC1 matrix
     * pls refer: https://in.mathworks.com/help/images/ref/imregionalmax.html for imregionalmax
     * eg: I/P
     *      10    10    10    10    10    10    10    10    10    10
            10    22    22    22    10    10    44    10    10    10
            10    22    22    22    10    10    10    45    10    10
            10    22    22    22    10    10    10    10    44    10
            10    10    10    10    10    10    10    10    10    10
            10    10    10    10    10    33    33    33    10    10
            10    10    10    10    10    33    33    33    10    10
            10    10    10    10    10    33    33    33    10    10
            10    10    10    10    10    10    10    10    10    10
            10    10    10    10    10    10    10    10    10    10
     * O/P
            0   0   0   0   0   0   0   0   0   0
            0   1   1   1   0   0   0   0   0   0
            0   1   1   1   0   0   0   1   0   0
            0   1   1   1   0   0   0   0   0   0
            0   0   0   0   0   0   0   0   0   0
            0   0   0   0   0   1   1   1   0   0
            0   0   0   0   0   1   1   1   0   0
            0   0   0   0   0   1   1   1   0   0
            0   0   0   0   0   0   0   0   0   0
            0   0   0   0   0   0   0   0   0   0
     * @param src
     * @param conn
     * @return cv::Mat
     */
    cv::Mat imregionalmax(cv::Mat& src)
    {
        //cv::Mat padded;
        //cv::copyMakeBorder(src, padded, 1, 1, 1, 1, cv::BORDER_CONSTANT, cv::Scalar::all(-1));
        cv::Mat padded;
        cv::copyMakeBorder(src, padded, 1, 1, 1, 1, cv::BORDER_REPLICATE);

        cv::Mat mx_ch1(padded.rows, padded.cols, CV_8UC1, cv::Scalar(2)); //Peak elements will be represented by 1, others by 0, initializing Mat with 2 for differentiation 
        cv::Mat mx[2] = { padded, mx_ch1 }; //mx[0] is padded image, mx[1] is regional maxima matrix
        int mx_rows = mx[0].rows;
        int mx_cols = mx[0].cols;
        cv::Mat dest(mx[0].size(), CV_8UC1);

        //Check each pixel for local max
        for (int row = 1; row < mx_rows - 1; row++) {
            for (int col = 1; col < mx_cols - 1; col++) {
                std::vector<cv::Point> conn_points; //this vector holds all connected points for candidate pixel
                cv::Point p(col, row);
                conn_points.push_back(p);
                bool isPartOfPeak = isPeak(mx, conn_points);
                if (isPartOfPeak) {
                    mx[1].at<uchar>(row, col) = 1;
                }
                else {
                    mx[1].at<uchar>(row, col) = 0;
                }
            }
        }
        dest = mx[1](cv::Rect(1, 1, src.cols, src.rows));
        return dest;
    }
}
cpp 复制代码
void test() {

    cv::Mat A = (cv::Mat_<float>(10, 10) <<
        10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
        10, 22, 22, 22, 10, 10, 44, 10, 10, 10,
        10, 22, 22, 22, 10, 10, 10, 45, 10, 10,
        10, 22, 22, 22, 10, 10, 10, 10, 44, 10,
        10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
        10, 10, 10, 10, 10, 33, 33, 33, 10, 10,
        10, 10,  9, 10, 10, 33, 33, 33, 10, 10,
        10,  9,  9,  9, 10, 33, 33, 33, 10, 10,
        10, 10,  9, 10, 10, 10, 10, 10, 10, 10,
        10, 10, 10, 10, 10, 10, 10, 10, 10, 10
        );

    //-- 查找区域最大值
    auto outFlags = MatlabCppCode::imregionalmax(A);
    std::cout <<"imregionalmax:\n"<< outFlags << std::endl;

	//-- 查找区域最小值
	cv::Mat revDataMat(10, 10, CV_32F);
	cv::normalize(A, revDataMat, 0, 1, cv::NORM_MINMAX);
	revDataMat = 1 - revDataMat;
    outFlags = MatlabCppCode::imregionalmax(revDataMat);
    std::cout << "imregionalmin:\n" << outFlags << std::endl;
}
相关推荐
委婉待续1 小时前
Qt的学习(二)
c++·qt
nenchoumi31192 小时前
UE5 学习系列(一)创建一个游戏工程
c++·学习·游戏·ue5
温宇飞2 小时前
C++ 作用域和标识符查找规则详解
c++
随意0232 小时前
STL 1 容器
开发语言·c++
cpp加油站3 小时前
拒绝切换IDE,10分钟让Trae编辑器化身C++神器,智能补全、编译调试一网打尽
c++·ai编程·trae
啊我不会诶3 小时前
篮球杯软件赛国赛C/C++ 大学 B 组补题
c语言·c++
l1t3 小时前
DeepSeek辅助实现的DuckDB copy to自定义函数
数据库·c++·人工智能
Bardb4 小时前
01__C++入门
c++·qt
weixin_457665395 小时前
C++11新标准
开发语言·c++
大白爱琴6 小时前
使用python进行图像处理—像素级操作与图像算术(4)
开发语言·图像处理·python