【问题标题】:opencv Mat memory access erroropencv Mat内存访问错误
【发布时间】:2017-12-07 05:43:04
【问题描述】:

我正在尝试编写一个函数来补偿 OpenCV 项目中的镜头渐晕。问题是,当我尝试访问 Mat 中的第一个像素时,出现内存访问错误。这可能是一个愚蠢的错误,但如果你能指出来,我将不胜感激。函数如下:

void EckOpCam::FlatField(cv::Mat & parmI)
{
// workaround for access violation error
cv::Mat I = parmI;
const int channels = I.channels();
if (flatField.rows == 0)
    MakeFlatFieldMat(I.rows);
// accept only char type matrices
ASSERT(I.depth() == CV_8U);
// make sure the matrices are the same size
ASSERT(I.cols == flatField.cols);
ASSERT(channels == flatField.channels());


// Try the really slow way...
int nRows = I.rows;
int nCols = I.cols;
unsigned int ipix0, ipix1, ipix2;   // B,G,r values of pixel in I
float fpix0, fpix1,fpix2;           // B,G,r values of pixel in flatField
float pix0, pix1, pix2;
switch (channels)
{
case 1:
    for (int y = 0; y < nRows; ++y)
        for (int x = 0; x < nCols; ++x)
        {
            {
                ipix0 = I.at<cv::Vec3b>(x, y)[0];
                fpix0 = flatField.at<cv::Vec3f>(x, y)[0];
                pix0 = ipix0 * fpix0;
                I.at<cv::Vec3b>(x, y)[0] = (pix0 > 255) ? 255 : uchar(pix0);
            }
        }
    break;
case 3:
    for (int y = 0; y < nRows; ++y)
        for (int x = 0; x < nCols; ++x)
        {
            {
                ipix0 = static_cast<uchar>(I.at<cv::Vec3b>(x, y)[0]); //<<< memory access error!
                ipix1 = static_cast<uchar>(I.at<cv::Vec3b>(x, y)[1]);
                ipix2 = static_cast<uchar>(I.at<cv::Vec3b>(x, y)[2]);
                fpix0 = flatField.at<cv::Vec3f>(x, y)[0];
                fpix1 = flatField.at<cv::Vec3f>(x, y)[1];
                fpix2 = flatField.at<cv::Vec3f>(x, y)[2];
                pix0 = ipix0 * fpix0;
                pix1 = ipix1 * fpix1;
                pix2 = ipix2 * fpix2;
                I.at<cv::Vec3b>(x, y)[0] = (pix0 > 255) ? 255 : uchar(pix0);
                I.at<cv::Vec3b>(x, y)[1] = (pix1 > 255) ? 255 : uchar(pix1);
                I.at<cv::Vec3b>(x, y)[2] = (pix2 > 255) ? 255 : uchar(pix2);
            }
        }
}

}

错误是:抛出异常:读取访问冲突。 cv::Vec::operator 返回 0x240C37EC4A8。

给出的地址正是 I.data 的地址。怎么了?感谢您的帮助。

【问题讨论】:

  • cv::Mat &amp; parmI 是否真的需要通过引用传递。 Mat类的赋值反正已经是指针赋值了。
  • 您所做的基本上不是饱和的每个元素乘法吗?就像 I = I.mul(flatField); 而不是所有的代码?
  • @macroland:是的,需要通过引用传递。我尝试按值传递,但没有返回任何图像。
  • @Dan:我很想使用 I.mul。不幸的是,图像是 CV_8UC3,而 flatField 矩阵是 CV_32FC3。我将尝试使用 I32.mul(flatField) 将图像转换为 CV_32FC3 并转换回来。感谢您的建议。
  • @dr_eck 哦,我错过了浮点类型。尽管如此,cv::multiply 也执行每个元素的饱和乘法,并允许您明确指定结果类型。所以cv::multiply(I, flatField, I, 1.0, CV_8UC3);

标签: c++ opencv


【解决方案1】:

嗯...没关系。事实证明,异常是真实的,而不是这段代码的问题。我正在使用 Point Grey 的示例代码。它使用仅将指针复制到数据的 Mat 构造函数将 Point Gray ImagePtr 转换为 Mat。 ImagePtr 超出范围,因此当我尝试使用它时数据无效。 Mat.CopyTo() 解决了这个问题。如果您需要快速解决类似问题的方法,我强烈建议您阅读 this

【讨论】:

    猜你喜欢
    • 2013-11-30
    • 1970-01-01
    • 2012-11-12
    • 1970-01-01
    • 1970-01-01
    • 2017-04-04
    • 1970-01-01
    • 2023-03-12
    • 1970-01-01
    相关资源
    最近更新 更多