You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

OpenCV C++遍历图像像素异常:仅部分区域颜色修改生效

问题:OpenCV修改图像颜色仅部分区域生效

我用C++结合OpenCV尝试修改图像颜色,但修改并未应用到整个图像区域。为测试问题,我尝试将图像所有像素设置为固定颜色(36, 81, 214),对于一张360×600的图像,因padding只处理全部358行,但仅前150列生效。我添加了final_i和final_j变量验证循环变量是否到达358、598,结果变量确实到达了对应值,但为何仅部分区域颜色被修改?

代码片段

Mat apply_convolution_kernel(Mat img_color, int kernel[][3], int kernel_size){
    int rows = img_color.rows;
    int cols = img_color.cols;

    Mat result = Mat(rows,cols, CV_32SC3, 0.0);
    cout<<img_color.rows<<" "<<img_color.cols<<endl;
    cout<<result.rows<<" "<<result.cols<<endl;

    int final_i = 0;
    int final_j = 0;
    // apply the kernel operator
    int aux_size = kernel_size / 2; // e.g for 3 x 3 kernel, we need [3/2] = 1 auxiliary padding
    for(int i=aux_size;i<rows - aux_size;i++){
        for(int j = aux_size;j<cols - aux_size;j++){

            Vec3b & pixel_from_res = result.at<Vec3b>(i,j);
            pixel_from_res[0] = 36;
            pixel_from_res[1] = 81;
            pixel_from_res[2] = 214;

            final_i = i;
            final_j = j;
        }
    }

    cout<<"final i: "<< final_i << " final j: "<<final_j<<endl;

    return result;
}


int main()
{
    cout << "Start" << endl;
    Mat img_color = imread("sakura.jpg", 1);
    int conv_size = 3;
    int conv_operator[3][3] = {
        {0, 1, 0},
        {1, 4, 1},
        {0, 1, 0}
        } ;
    Mat m1 =apply_convolution_kernel(img_color, conv_operator,3);
    imwrite("filter.jpg", m1);

    return 0;
}

问题原因与解决方法

核心问题:图像类型与像素访问类型不匹配

你创建的结果图像result是CV_32SC3类型(3通道32位有符号整数,每个像素占12字节),但访问像素时却用了Vec3b——这个类型对应8位无符号三通道(CV_8UC3,每个像素占3字节)。

这种类型不匹配会导致内存访问错位:每读取4个Vec3b对应的内存,才相当于1个CV_32SC3像素的内存。反映到图像上,就是实际修改的列数只有原列数的1/4(600÷4=150),和你看到的现象完全吻合。

解决方法

有两种可行的修正方式:

  1. 统一图像类型为8位无符号(推荐)
    创建结果图像时,使用和原图一致的CV_8UC3类型,或者直接显式指定:

    Mat result = Mat(rows, cols, CV_8UC3, Scalar(0, 0, 0));
    

    这种方式也符合imwrite的要求(imwrite默认只支持8位无符号类型的图像保存,避免后续保存时出现颜色失真或异常)。

  2. 匹配像素访问类型
    如果坚持使用CV_32SC3类型的结果图,需要用对应Vec3i类型访问像素:

    Vec3i &pixel_from_res = result.at<Vec3i>(i,j);
    pixel_from_res[0] = 36;
    pixel_from_res[1] = 81;
    pixel_from_res[2] = 214;
    

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 09:47:29