【问题标题】:image.rows and image.cols are less than real image size (c++)image.rows 和 image.cols 小于真实图像大小(c++)
【发布时间】:2020-01-24 21:12:05
【问题描述】:

我正在学习 open cv,我编写了一个代码,应该为图像添加盐和纸张噪声(它将一些随机像素的值变为 255),我的图像大小是 256256。问题是我无法访问所有像素,代码只改变了图像像素的一半。例如,我所说的图像大小是 256256,当我更改位于 256*256 中的像素值时,它会更改中心图像的像素。

inline cv::Mat salt(cv::Mat, int); //my function

int main()
{

     int present, imagepixel;
     cv::Mat image = cv::imread("sample.jpg");
     imagepixel = image.rows * image.cols;
     std::cout << "enter the value of salt and paper :";
     std::cin >> percent; 
     present = (present * imagepixel) / 100; //image pixel is number of image's pixels

     if (image.empty())
     {
          std::cout << "image is not valid" << std::endl;
     }

     image = salt(image, present);
     cv::imshow("salt&paper", image);
     cv::waitKey(0);
     return 0;
}

cv::Mat salt(cv::Mat image, int present)
{
     int row, col, j = 0;
     srand(time(NULL));
         
     for (int i = 0; i < present; i++)
     {
          row = rand() % image.rows;
          col = rand() % image.cols;
          image.at<unsigned char>(row, col) = 255;
     }
     return image;
}
  1. 为什么图像的行和列比使用image.rowsimage.cols 之类的函数计算的要多(我在调试模式和图像中将值赋予图像,其值超出了 image.rows 和 image.cols 范围)?

  2. 为什么输出设置为无符号字符?为什么像素的值不能是整数? (我以为image.at&lt;unsigned char&gt;, &lt;unsigned char&gt;里面是输出类型(int, char, float)

  3. 为什么这段代码不能访问所有像素? (截图有加看输出)

【问题讨论】:

    标签: c++ image opencv


    【解决方案1】:

    imread 的第二个参数指定如何读取图像。默认值为IMREAD_COLOR是什么意思:

    在彩色图像的情况下,解码后的图像将具有通道 以 B G R 顺序存储。 (from reference)

    所以您的结果 mat 具有 256x256 分辨率,每个像素由 3 个值描述:存储 BlueGreen红色空间颜色的组成部分。这些组件存储在uchar 类型上(范围为[0,255))。

    OpenCV 中的二维图像是逐行存储的。下面的公式可以用来计算M(row,col)元素的地址:

    addr(M[row,col]) = data + step1 * row + step2 * col 
    

    其中data 是存储图像数据的数组的第一个字节。你的 mat 有 3 个通道,图像的宽度是 256,所以 step1 等于 256 * 3(它是行中的列数乘以每个像素的通道数)并且 step23.

    现在,我们将at成员函数的源代码开源:

    template<typename _Tp> inline
    _Tp& Mat::at(int i0, int i1) {
        return ((_Tp*)(data + step.p[0] * i0))[i1];
    }
    // i0 means row, i1 means col
    

    在您的代码中,您将_Tp 指定为uchar。现在只是指针算术规则,导致您只能访问 1/3 的输入图像。例如,当您调用&lt;uchar&gt;(0,1) 时,您正在访问(0,0) 像素的Green 组件。

    要解决您的问题,您必须在模板参数列表中传递 Vec3b

    image.at<cv::Vec3b>(row, col) = cv::Vec3b(255,255,255);
    

    (Vec3b 的每个组件都有uchar 类型)。

    【讨论】:

    • 您好,感谢您的回答。我的图像是黑白的。这不能成为一个频道图像的理由吗?
    • 如果您的输入图像是带有灰度的JPG,当imreadIMREAD_COLOR输出图像将有3个通道并且所有通道具有相同的值。你可以用IMREAD_GRAYSCALE 调用imread,然后通过at&lt;uchar&gt; 访问mat 的元素——你的输出mat 将有一个通道,它应该可以工作。
    • imread 的默认值是什么? (imread 没有 _grayscare 或 _color)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多