OpenCV:将一个图像复制到另一个图像时出错

时间:2014-06-24 20:11:20

标签: c++ opencv computer-vision runtime-error pixel

我正在尝试将一个图像复制到另一个像素(我知道有复杂的方法可用。我正在尝试解决另一个问题并且回答这个问题会很有用)。

这是我的代码:

int main()
{
    Mat Img;
    Img = imread("../../../stereo_images/left01.jpg");

    Mat copyImg = Mat::zeros(Img.size(), CV_8U);
    for(int i=0; i<Img.rows; i++){
        for(int j=0; j<Img.cols; j++){
            copyImg.at<uchar>(j,i) = Img.at<uchar>(j,i);
        }}
    namedWindow("Image", CV_WINDOW_AUTOSIZE );
    imshow("Image", Img);
    namedWindow("copyImage", CV_WINDOW_AUTOSIZE );
    imshow("copyImage", copyImg);
    waitKey(0);
    return 0;
}

当我在visual studio中运行此代码时,我收到以下错误

OpenCV Error: Assertion failed (dims <= 2 && data && (unsigned)i0 < (unsigned)si
ze.p[0] && (unsigned)(i1*DataType<_Tp>::channels) < (unsigned)(size.p[1]*channel
s()) && ((((sizeof(size_t)<<28)|0x8442211) >> ((DataType<_Tp>::depth) & ((1 << 3
) - 1))*4) & 15) == elemSize1()) in cv::Mat::at, file c:\opencv\opencv-2.4.9\ope
ncv\build\include\opencv2\core\mat.hpp, line 537

我知道Img的类型是CV_8U。为什么会这样?

谢谢!

3 个答案:

答案 0 :(得分:5)

// will read in a rgb image , no matter what the content is
Img = imread("../../../stereo_images/left01.jpg"); 

使其读取灰度图像使用:

Img = imread("../../../stereo_images/left01.jpg", CV_LOAD_IMAGE_GRAYSCALE); 

然后,你不需要复制每个像素(你甚至应该避免这种情况),只需使用:

Mat im2 = Img.clone();

如果你进行逐像素循环,请注意使索引正确。它在这里的行col世界,而不是x,y,所以它应该是:

 copyImg.at<uchar>(i,j) = Img.at<uchar>(i,j);

在你的情况下

答案 1 :(得分:3)

你的问题在于这一行:

copyImg.at<uchar>(j,i) = Img.at<uchar>(j,i);

应该是:

copyImg.at<uchar>(i,j) = Img.at<uchar>(i,j);

请注意,如果您想复制图片,可以执行以下操作:

Mat copyImg = Img.clone();

答案 2 :(得分:3)

  

我知道Img的类型是CV_8U。

但CV_8U只是图像深度( 8 - 位 U - 已签名)。该类型还指定了通道数,通常为三个。一个用于蓝色,一个用于绿色,一个用于红色,默认为OpenCV。类型为CV_8UC3( C -hannels = 3 )。默认情况下,imread甚至会将黑白图像转换为3通道图像。 imread(filename, CV_LOAD_IMAGE_GRAYSCALE)将加载1通道图像(CV_8UC1)。但如果您不确定最简单的解决方案是

Mat copyImg = Mat::zeros(Img.size(), Img.type());

要访问数组元素,您必须知道它的大小。在3通道图像上使用.at<uchar>()只能访问第一个通道,因为每个像素有3 * 8位。因此,在3通道图像上,您必须使用

copyImg.at<Vec3b>(i,j) = Img.at<Vec3b>(i,j);

其中Vec3bcv::Vec<uchar, 3>。您还应该注意at<>(,)的第一个参数是沿着dim 0的索引,它们是行和第二个参数cols。或者换句话说,在经典的2d-xy-chart顺序中,您可以使用.at<>(y,x) == .at<>(Point(x,y))访问像素。