【OpenCV】实现 argmax 得到像素点分类

1. cv::Mat 与 float 数组互转

​(1) cv::Mat 转 float 数组
// 假设 mat 是 CV_32FC3 类型(3通道浮点矩阵)
cv::Mat mat = cv::Mat::ones(100, 100, CV_32FC3); 

// 检查矩阵是否连续存储
if (!mat.isContinuous()) {
    mat = mat.clone(); // 转为连续内存
}

// 获取数据指针
float* float_array = (float*)mat.data;

// 验证数据(示例:访问第一个像素的通道值)
float b = float_array[0];
float g = float_array[1];
float r = float_array[2];
​​(2) float 数组转 cv::Mat
// 假设数组是 100x100x3 的浮点数据
float* float_data = new float[100 * 100 * 3]; 
// ... 填充数据 ...

// 创建 cv::Mat(深拷贝)
cv::Mat mat_from_array(100, 100, CV_32FC3, float_data); // 浅拷贝(注意内存生命周期)
// 或者深拷贝:
cv::Mat mat_deep;
mat_deep.create(100, 100, CV_32FC3);
memcpy(mat_deep.data, float_data, 100 * 100 * 3 * sizeof(float));

2. 实现 argmax 获取像素分类

​(1) 场景说明

假设输入矩阵为多通道 cv::Mat(例如 ​语义分割的输出,每个通道表示类别概率),需找到每个像素的 ​最大概率对应的通道索引

​(2) 核心代码
/​**​
 * @brief 对多通道浮点矩阵执行 argmax,生成单通道分类结果
 * @param src 输入矩阵(CV_32FC3、CV_32FC4 等多通道浮点类型)
 * @return 单通道分类索引矩阵(CV_8UC1 或 CV_32SC1)
 */
cv::Mat argmax(const cv::Mat& src) {
    // 检查输入类型
    CV_Assert(src.type() == CV_32FC3 || src.type() == CV_32FC(4)); 

    const int channels = src.channels();
    cv::Mat dst(src.rows, src.cols, CV_8UC1); // 输出单通道索引

    for (int r = 0; r < src.rows; r++) {
        const float* src_ptr = src.ptr<float>(r);
        uchar* dst_ptr = dst.ptr<uchar>(r);
        
        for (int c = 0; c < src.cols; c++) {
            float max_val = src_ptr[c * channels];
            uchar max_idx = 0;
            
            // 遍历每个通道,寻找最大值索引
            for (int ch = 1; ch < channels; ch++) {
                if (src_ptr[c * channels + ch] > max_val) {
                    max_val = src_ptr[c * channels + ch];
                    max_idx = ch;
                }
            }
            
            dst_ptr[c] = max_idx; // 记录分类结果
        }
    }
    
    return dst;
}
​(3) 使用示例
// 模拟语义分割输出(3通道概率图)
cv::Mat prob_map(480, 640, CV_32FC3);
cv::randu(prob_map, 0.0, 1.0); // 随机生成概率

// 执行 argmax
cv::Mat class_idx = argmax(prob_map);

// 可视化分类结果(不同类别用不同颜色)
cv::Mat color_map;
cv::applyColorMap(class_idx * 80, color_map, cv::COLORMAP_JET); // 伪彩色映射
cv::imshow("Classification", color_map);
cv::waitKey(0);

3. 关键注意事项

  1. 数据类型匹配​:

    • 输入矩阵必须是 CV_32FC1CV_32FC3 等浮点类型。
    • 输出分类索引矩阵根据类别数量选择类型(如类别数 < 256 用 CV_8UC1,否则用 CV_32SC1)。
  2. 内存连续性​:

    • 使用 mat.isContinuous() 检查内存布局,必要时用 mat.clone() 保证连续。
  3. 性能优化​:

    • 多通道遍历时,优先使用指针操作而非 at<T>() 方法。
    • 可并行化处理(如 OpenMP 加速)。
  4. 分类结果后处理​:

    • 对分类结果进行形态学滤波(如 cv::medianBlur)可消除噪声。
    • 结合阈值过滤低置信度区域。

通过以上方法,可以实现高效的像素级分类,适用于语义分割、多类别目标检测等场景。

参考:

  1. cv::Mat 与 float 互换,实现 argmax 得到像素点分类 - 简书
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

浩瀚之水_csdn

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

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

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

打赏作者

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

抵扣说明:

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

余额充值