You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何实现可处理不同类型图像的OpenCV函数及Mat行删除问题

嘿,我来帮你搞定这两个问题——既要学会编写能处理不同类型图像的OpenCV通用函数,还要把你现在写的两个重复的「删除指定行」函数合并成一个通用版本,避免冗余代码。

处理多类型图像的OpenCV函数实现方案

一、编写通用型OpenCV函数的核心思路

要适配不同数据类型的图像(比如单通道的CV_8UC1CV_32SC1,或者多通道的CV_64FC3),最省心的方法是用C++模板函数。它能让同一套逻辑自动适配多种数据类型,不用为每个类型单独写重复代码。

关键技巧:

  • 用模板参数<typename T>指定像素的数据类型,比如intfloatcv::Vec3b(对应三通道8位图像)
  • 搭配OpenCV自带的DataType<T> traits类,可以方便获取类型对应的OpenCV枚举值(比如CV_32SC1
  • 处理多通道图像时,记得用对应的向量类型(比如cv::Vec3f对应三通道float图像)

二、把你的「删除指定行」函数改成通用版本

你现在写的是针对CV_32SC1(int类型单通道)的函数,我们把它改成模板函数,这样不管是int、float还是其他类型的Mat,都能用同一个函数处理:

通用版完整代码

#include <opencv2/opencv.hpp>
#include <algorithm>
#include <vector>

template<typename T>
cv::Mat drop_rows(const cv::Mat& mat, const std::vector<int>& rows_to_drop) {
    // 先做基础合法性检查
    if (mat.empty()) {
        return cv::Mat();
    }
    if (rows_to_drop.empty()) {
        return mat.clone();
    }

    // 对要删除的行号排序并去重,提升后续查找效率
    std::vector<int> sorted_drop_rows = rows_to_drop;
    std::sort(sorted_drop_rows.begin(), sorted_drop_rows.end());
    auto last = std::unique(sorted_drop_rows.begin(), sorted_drop_rows.end());
    sorted_drop_rows.erase(last, sorted_drop_rows.end());

    // 计算新矩阵的行数,若删除后无行则返回空矩阵
    int new_row_count = mat.rows - sorted_drop_rows.size();
    if (new_row_count <= 0) {
        return cv::Mat();
    }

    // 创建和输入类型完全一致的新矩阵
    cv::Mat new_mat(new_row_count, mat.cols, mat.type());

    int dst_idx = 0;
    auto drop_iter = sorted_drop_rows.begin();
    for (int src_idx = 0; src_idx < mat.rows; ++src_idx) {
        // 判断当前行是否在删除列表中
        if (drop_iter != sorted_drop_rows.end() && *drop_iter == src_idx) {
            ++drop_iter;
            continue;
        }
        // 直接复制整行到新矩阵,比逐像素拷贝更高效
        mat.row(src_idx).copyTo(new_mat.row(dst_idx));
        ++dst_idx;
    }

    return new_mat;
}

使用示例(适配不同类型)

// 测试int类型单通道矩阵
cv::Mat int_mat = (cv::Mat_<int>(3, 2) << 1, 2, 3, 4, 5, 6);
std::vector<int> drop_int = {1};
cv::Mat result_int = drop_rows<int>(int_mat, drop_int);

// 测试float类型单通道矩阵
cv::Mat float_mat = (cv::Mat_<float>(4, 3) << 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, 10.1, 11.2, 12.3);
std::vector<int> drop_float = {0, 2};
cv::Mat result_float = drop_rows<float>(float_mat, drop_float);

// 测试三通道8位图像(用cv::Vec3b作为模板参数)
cv::Mat rgb_mat = cv::imread("test.jpg");
std::vector<int> drop_rgb = {50, 100};
cv::Mat result_rgb = drop_rows<cv::Vec3b>(rgb_mat, drop_rgb);

三、其他通用图像处理函数的示例

再举个简单例子:写一个给所有像素加常数的通用函数,适配任意类型:

template<typename T>
cv::Mat add_pixel_constant(const cv::Mat& mat, const T& constant) {
    cv::Mat result(mat.size(), mat.type());
    // 用OpenCV的遍历器更简洁,也支持多通道
    cv::Mat_<T> src_mat = mat;
    cv::Mat_<T> dst_mat = result;
    for (int i = 0; i < src_mat.rows; ++i) {
        for (int j = 0; j < src_mat.cols; ++j) {
            dst_mat(i, j) = src_mat(i, j) + constant;
        }
    }
    return result;
}

避坑小贴士

  • 模板函数要放在头文件里实现,或者在使用前显式实例化(不然编译器可能找不到定义)
  • 可以用CV_Assert做严格的类型检查,比如确保输入Mat的类型和模板参数匹配:CV_Assert(mat.type() == cv::DataType<T>::type);
  • 处理多通道图像时,一定要用对应的向量类型(比如cv::Vec3b对应CV_8UC3cv::Vec3f对应CV_32FC3

内容的提问来源于stack exchange,提问作者tem

火山引擎 最新活动