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

C++实现imregionalmax函数

1 说明

Matlab imregionalmax

BW = imregionalmax(I)  

返回标识灰度图像 I 中区域最大值的二值图像BW。
区域最大值点是具有同一强度值的连通像素分量,其周围的像素强度值比该值低。
BW — 逻辑数组
区域最大值的位置,以与 I 大小相同的逻辑数组形式返回。值为 1 的像素表示区域最大值;所有其他像素设置为 0。

2 示例

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

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

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
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) 处的区域最大值。

regmax = imregionalmax(A)
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++实现

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;
    }
}
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;
}

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

waf13916

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值