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;
}
相关推荐
phoenix@Capricornus18 分钟前
矩阵的对角化&特征值分解
图像处理·线性代数·机器学习·矩阵
ROC_bird..1 小时前
STL - vector的使用和模拟实现
开发语言·c++
机器视觉知识推荐、就业指导1 小时前
C++中的栈(Stack)和堆(Heap)
c++
金蝶软件小李2 小时前
基于深度学习的猫狗识别
图像处理·深度学习·计算机视觉
shishi5212 小时前
开源项目推荐——OpenDroneMap无人机影像数据处理
图像处理·无人机
Mr_Xuhhh3 小时前
递归搜索与回溯算法
c语言·开发语言·c++·算法·github
无敌岩雀3 小时前
C++设计模式行为模式———命令模式
c++·设计模式·命令模式
这是一个图像4 小时前
从opencv-python入门opencv--图像处理之图像滤波
图像处理·opencv·计算机视觉·中值滤波·高斯滤波·双边滤波·图像滤波
爱吃生蚝的于勒5 小时前
C语言内存函数
c语言·开发语言·数据结构·c++·学习·算法
小白学大数据7 小时前
Python爬虫开发中的分析与方案制定
开发语言·c++·爬虫·python