Ask Your Question
0

help finding memory corruption in code that writes to a cv::Mat

asked 2017-08-24 17:21:22 -0600

Please note, I am not the author of the code that has the problem below. I am having trouble running the https://github.com/CMU-Perceptual-Com... that uses opencv.

You can see the valgrind report here: https://github.com/CMU-Perceptual-Com...

Valgrind reports that the code writes 1 byte past allocated memory in this function: https://github.com/CMU-Perceptual-Com...

void floatPtrToUCharCvMat(cv::Mat& cvMat, const float* const floatImage, const Point<int>& resolutionSize, const int resolutionChannels)
{   
    try 
    {   
        // float* (deep net format): C x H x W 
        // cv::Mat (OpenCV format): H x W x C 
        if (cvMat.rows != resolutionSize.y || cvMat.cols != resolutionSize.x || cvMat.type() != CV_8UC3)
            cvMat = cv::Mat(resolutionSize.y, resolutionSize.x, CV_8UC3);
        const auto offsetBetweenChannels = resolutionSize.x * resolutionSize.y;
        for (auto c = 0; c < resolutionChannels; c++)
        {   
            const auto offsetChannelC = c*offsetBetweenChannels;
            for (auto y = 0; y < resolutionSize.y; y++)
            {   
                const auto floatImageOffsetY = offsetChannelC + y*resolutionSize.x;
                for (auto x = 0; x < resolutionSize.x; x++)
                {   
                    const auto value = uchar(   fastTruncate(intRound(floatImage[floatImageOffsetY + x]), 0, 255)   );  
                    *(cvMat.ptr<uchar>(y) + x*resolutionChannels + c) = value;
                }   
            }   
        }   
    }   
    catch (const std::exception& e)
    {   
        error(e.what(), __LINE__, __FUNCTION__, __FILE__);
    }   
}

This code looks pretty scary because it breaks encapsulation.

*(cvMat.ptr<uchar>(y) + x*resolutionChannels + c) = value;

It would be so much cleaner if it was cvMat[y][x][c] = value or cvMat.setValue(x, y, c, value);

Can you tell me if this code looks correct to you? I think the function is called many times without a memory issue being reported by valgrind.

edit retag flag offensive close merge delete

2 answers

Sort by ยป oldest newest most voted
0

answered 2017-08-27 23:32:22 -0600

I found the answer. I made 3 changes:

  1. I initialized a local cv::Mat that is passed into the function with the desired size.
  2. The function was calling cv::Mat{rows, cols, type} but the instance wasn't initialized as expected. Changing to cv:Mat(rows, cols, type) fixed that. (Maybe my compiler options are not set correctly)
  3. I changed the update logic to *(cvMat.ptr<uchar>(y, x) + c) = value; to be safer.
edit flag offensive delete link more
0

answered 2017-08-25 12:32:13 -0600

pklab gravatar image

updated 2017-08-25 12:36:33 -0600

I would build a cv::Mat over existing data than convert to BGR using Mat::convertTo

// build a cv::Mat over existing data
cv::Mat cvMatFloat(resolutionSize.y,resolutionSize.x,CV_32FC3,(void*)floatImage);
// convert to BGR image
cvMatFloat.convertTo(cvMat,CV_8UC3);
edit flag offensive delete link more

Question Tools

1 follower

Stats

Asked: 2017-08-24 17:21:22 -0600

Seen: 1,768 times

Last updated: Aug 27 '17