当前位置: 首页 > article >正文

像素的访问和算术运算

【欢迎关注编码小哥,学习更多实用的编程方法和技巧】

一、常用的访问像素的方法

1、使用at()方法

// 灰度图
cv::Mat grayImage;
for (int y = 0; y < grayImage.rows; y++) {
    for (int x = 0; x < grayImage.cols; x++) {
        uchar pixel = grayImage.at<uchar>(y, x);
        // 处理像素
        grayImage.at<uchar>(y, x) = pixel + 10;
    }
}

// 彩色图
cv::Mat colorImage;
for (int y = 0; y < colorImage.rows; y++) {
    for (int x = 0; x < colorImage.cols; x++) {
        cv::Vec3b pixel = colorImage.at<cv::Vec3b>(y, x);
        // 处理像素
        pixel[0] = pixel[0] + 10; // B通道
        pixel[1] = pixel[1] + 10; // G通道
        pixel[2] = pixel[2] + 10; // R通道
        colorImage.at<cv::Vec3b>(y, x) = pixel;
    }
}

2、使用指针遍历

// 灰度图
cv::Mat grayImage;
for (int y = 0; y < grayImage.rows; y++) {
    uchar* row = grayImage.ptr<uchar>(y);
    for (int x = 0; x < grayImage.cols; x++) {
        row[x] = row[x] + 10;
    }
}

// 彩色图
cv::Mat colorImage;
for (int y = 0; y < colorImage.rows; y++) {
    cv::Vec3b* row = colorImage.ptr<cv::Vec3b>(y);
    for (int x = 0; x < colorImage.cols; x++) {
        row[x][0] = row[x][0] + 10; // B通道
        row[x][1] = row[x][1] + 10; // G通道
        row[x][2] = row[x][2] + 10; // R通道
    }
}

3、迭代器遍历

// 灰度图
cv::Mat grayImage;
cv::MatIterator_<uchar> it, end;
for (it = grayImage.begin<uchar>(), end = grayImage.end<uchar>(); it != end; ++it) {
    *it = *it + 10;
}

// 彩色图
cv::Mat colorImage;
cv::MatIterator_<cv::Vec3b> it, end;
for (it = colorImage.begin<cv::Vec3b>(), end = colorImage.end<cv::Vec3b>(); it != end; ++it) {
    (*it)[0] = (*it)[0] + 10; // B通道
    (*it)[1] = (*it)[1] + 10; // G通道
    (*it)[2] = (*it)[2] + 10; // R通道
}

4、forEach()方法(C++11)

// 灰度图
cv::Mat grayImage;
grayImage.forEach<uchar>([](uchar &pixel, const int * position) {
    pixel = pixel + 10;
});

// 彩色图
cv::Mat colorImage;
colorImage.forEach<cv::Vec3b>([](cv::Vec3b &pixel, const int * position) {
    pixel[0] = pixel[0] + 10; // B通道
    pixel[1] = pixel[1] + 10; // G通道
    pixel[2] = pixel[2] + 10; // R通道
});

二、基于image.data直接访问像素数据方法 

1、数据访问基础

// 获取图像基本信息
int width = image.cols;
int height = image.rows;
int channels = image.channels();
uchar* pixelPtr = image.data;

2、灰度图像访问

cv::Mat grayImage;
for (int y = 0; y < grayImage.rows; y++) {
    for (int x = 0; x < grayImage.cols; x++) {
        // 直接通过data指针访问
        uchar* pixel = grayImage.data + y * grayImage.step + x;
        *pixel = *pixel + 10; // 像素处理
    }
}

 3、彩色图像访问

cv::Mat colorImage;
for (int y = 0; y < colorImage.rows; y++) {
    for (int x = 0; x < colorImage.cols; x++) {
        // 计算像素位置
        int index = y * colorImage.step + x * colorImage.channels();
        
        // BGR通道
        uchar blue = colorImage.data[index];
        uchar green = colorImage.data[index + 1];
        uchar red = colorImage.data[index + 2];
        
        // 修改像素
        colorImage.data[index] = blue + 10;
        colorImage.data[index + 1] = green + 10;
        colorImage.data[index + 2] = red + 10;
    }
}

 4、通用像素访问模板

template<typename T>
void processImage(cv::Mat& image) {
    int channels = image.channels();
    
    for (int y = 0; y < image.rows; y++) {
        for (int x = 0; x < image.cols; x++) {
            // 计算像素起始位置
            int index = y * image.step + x * channels;
            
            // 根据通道数处理
            if (channels == 1) {
                T& pixel = reinterpret_cast<T&>(image.data[index]);
                pixel = pixel + 10;
            } else if (channels == 3) {
                T* pixel = reinterpret_cast<T*>(&image.data[index]);
                pixel[0] = pixel[0] + 10; // B
                pixel[1] = pixel[1] + 10; // G
                pixel[2] = pixel[2] + 10; // R
            }
        }
    }
}

// 使用示例
cv::Mat grayImage(height, width, CV_8UC1);
cv::Mat colorImage(height, width, CV_8UC3);

processImage<uchar>(grayImage);
processImage<uchar>(colorImage);

5、高级数据访问 

class ImageProcessor {
private:
    cv::Mat image;
    uchar* data;
    int width, height, channels, step;

public:
    ImageProcessor(cv::Mat& img) : image(img) {
        data = image.data;
        width = image.cols;
        height = image.rows;
        channels = image.channels();
        step = image.step;
    }

    // 安全的像素访问
    uchar& pixel(int x, int y, int channel = 0) {
        return data[y * step + x * channels + channel];
    }

    // 像素处理
    void process() {
        for (int y = 0; y < height; y++) {
            for (int x = 0; x < width; x++) {
                // 处理每个通道
                for (int c = 0; c < channels; c++) {
                    uchar& p = pixel(x, y, c);
                    p = cv::saturate_cast<uchar>(p * 1.2);
                }
            }
        }
    }
};

// 使用
cv::Mat image = cv::imread("image.jpg");
ImageProcessor processor(image);
processor.process();

三、像素算术运算 

1、基本像素算术运算

// 像素加法
cv::Mat result = image1 + image2;

// 像素减法
cv::Mat result = image1 - image2;

// 像素乘法
cv::Mat result = image1.mul(image2);

// 像素除法
cv::Mat result = image1 / image2;

2、标量运算

// 对整个图像进行标量运算
cv::Mat brightened = image + 50;  // 增加亮度
cv::Mat darkened = image - 50;    // 降低亮度
cv::Mat increased_contrast = image * 1.5;  // 增加对比度
cv::Mat decreased_contrast = image * 0.5;  // 降低对比度

3、像素逐元素运算

// 自定义像素运算函数
cv::Mat pixelWiseOperation(const cv::Mat& src) {
    cv::Mat dst = src.clone();
    
    // 遍历每个像素
    for (int y = 0; y < dst.rows; y++) {
        for (int x = 0; x < dst.cols; x++) {
            // 灰度图
            if (dst.channels() == 1) {
                uchar& pixel = dst.at<uchar>(y, x);
                pixel = cv::saturate_cast<uchar>(std::pow(pixel, 1.2));
            }
            // 彩色图
            else if (dst.channels() == 3) {
                cv::Vec3b& pixel = dst.at<cv::Vec3b>(y, x);
                pixel[0] = cv::saturate_cast<uchar>(std::pow(pixel[0], 1.2));
                pixel[1] = cv::saturate_cast<uchar>(std::pow(pixel[1], 1.2));
                pixel[2] = cv::saturate_cast<uchar>(std::pow(pixel[2], 1.2));
            }
        }
    }
    return dst;
}

4、通道分离与运算

// 分离通道并对特定通道进行运算
cv::Mat performChannelOperation(const cv::Mat& src) {
    std::vector<cv::Mat> channels;
    cv::split(src, channels);

    // 对蓝色通道进行操作
    channels[0] = channels[0] * 1.5;

    cv::Mat result;
    cv::merge(channels, result);
    return result;
}

5、安全像素运算模板

template<typename T>
cv::Mat safePixelOperation(const cv::Mat& src, double factor) {
    cv::Mat dst = src.clone();
    
    for (int y = 0; y < dst.rows; y++) {
        for (int x = 0; x < dst.cols; x++) {
            if (dst.channels() == 1) {
                T& pixel = dst.at<T>(y, x);
                pixel = cv::saturate_cast<T>(pixel * factor);
            }
            else if (dst.channels() == 3) {
                T* pixel = dst.at<T>(y, x);
                pixel[0] = cv::saturate_cast<T>(pixel[0] * factor);
                pixel[1] = cv::saturate_cast<T>(pixel[1] * factor);
                pixel[2] = cv::saturate_cast<T>(pixel[2] * factor);
            }
        }
    }
    return dst;
}

// 使用示例
cv::Mat result8U = safePixelOperation<uchar>(image, 1.5);
cv::Mat result16U = safePixelOperation<ushort>(image16, 1.5);

6、复杂像素运算

// 多图像混合
cv::Mat blendImages(const cv::Mat& img1, const cv::Mat& img2, double alpha = 0.5) {
    cv::Mat blended;
    cv::addWeighted(img1, alpha, img2, 1 - alpha, 0, blended);
    return blended;
}

// 图像映射变换
cv::Mat gammaCorrection(const cv::Mat& src, double gamma = 1.0) {
    cv::Mat dst;
    src.convertTo(dst, CV_32F, 1.0/255);
    cv::pow(dst, gamma, dst);
    dst = dst * 255;
    dst.convertTo(dst, CV_8U);
    return dst;
}

7、位运算 

// 位运算
cv::Mat bitwiseOperations(const cv::Mat& src) {
    cv::Mat mask = src > 128;  // 创建二值化掩膜
    
    cv::Mat result1, result2;
    cv::bitwise_and(src, mask, result1);     // 与运算
    cv::bitwise_or(src, mask, result2);      // 或运算
    
    return result1;
}

8、高级像素映射

// 自定义像素映射
cv::Mat customPixelMapping(const cv::Mat& src) {
    cv::Mat lookupTable(1, 256, CV_8U);
    uchar* lut = lookupTable.ptr();
    
    // 创建查找表
    for (int i = 0; i < 256; i++) {
        lut[i] = cv::saturate_cast<uchar>(std::sin(i * CV_PI / 255.0) * 255.0);
    }
    
    cv::Mat result;
    cv::LUT(src, lookupTable, result);
    return result;
}

注意事项

  1. 使用cv::saturate_cast防止溢出
  2. 注意数据类型转换
  3. 考虑图像通道数
  4. 处理边界情况
  5. 性能优化

性能建议

  1. 使用cv::Mat操作替代逐像素遍历
  2. 利用OpenCV的矩阵运算
  3. 对于大图像,考虑并行处理
  4. 使用cv::cuda进行GPU加速


http://www.kler.cn/a/463495.html

相关文章:

  • 我的桌面 1.9.75 | 个性化定制手机桌面,丰富的小组件和主题
  • 探索Docker Compose:轻松管理多容器应用
  • 项目优化之策略模式
  • mysql 忘记root密码 无密码登录系统 配置文件怎么改?
  • vue中的设计模式
  • 计算帐户每月余额,补齐缺失日期:从 SQL 到 SPL
  • 【R语言】校准曲线,绘制原理
  • 游戏关卡设计方法的杂感
  • 【Unity3d】C#浮点数丢失精度问题
  • 如何查询快手IP归属地?如何关闭
  • HTML——46.制作课程表
  • 鸿蒙应用开发 - 如何去掉字符串中空格
  • 使用 `Celery` 与 `RabbitMQ` 实现异步任务队列:构建高效、可靠的任务调度系统
  • 深度学习在光学成像中是如何发挥作用的?
  • [创业之路-222]:波士顿矩阵与GE矩阵在业务组合选中作用、优缺点比较
  • 如何通过深度学习提升大分辨率图像预测准确率?
  • Ajax阶段总结(二维表+思维导图+四种请求方式)
  • 数据库概念(MySQL第一期)
  • MongoDB 固定集合
  • AWTK 在 ESP 上的移植笔记
  • quasar v2 setup语法中报错: undefined is not an object (evaluating ‘this.$q.notify‘)
  • 使用 Actix-Web、SQLx 和 Redis 构建高性能 Rust Web 服务
  • 电子电气架构 --- 安全相关内容汇总
  • HeidiSQL导入与导出数据
  • 【GO基础学习】Go操作数据库MySQL
  • webpack打包node后端项目