我试图在视频帧上绘制10 * 10矩阵,这是绘图函数:
void AddMatrixToVideo::process(cv::Mat &videoFrameInput)
{
int MatrixStartPointX = 0;
int MatrixStartPointY = 0;
int m,n;
for(int i = 0; i < matrixNumInRow; ++i) {
for(int j = 0; j < matrixNumInColm; ++j) {
//draw horizontal line
for(m = MatrixStartPointX; m < MatrixStartPointX + matrixWidth; ++m) {
processGrayFrame(m,MatrixStartPointY,videoFrameInput);
processGrayFrame(m,MatrixStartPointY + matrixHeight,videoFrameInput);
}
//draw vertical line
for(n = MatrixStartPointY; n < MatrixStartPointY + matrixHeight; ++n) {
// processGrayFrame(MatrixStartPointX,n,videoFrameInput);
// processGrayFrame(MatrixStartPointX + matrixWidth,n,videoFrameInput);
}
MatrixStartPointX += matrixWidth;
}
MatrixStartPointX = 0;
MatrixStartPointY += matrixHeight;
}
}
这是processGrayFrame():
void AddMatrixToVideo::processGrayFrame(int x,int y,cv::Mat &videoFrameInput)
{
videoFrameInput.at<uchar>(y,x) = 255;
}
运行程序后,似乎绘图进度正常,内存使用量不断增加,最终耗尽内存。 如果我评论processGrameFrame()函数,内存问题就会消失(当然它不会再画线)。所以我的问题是为什么分配操作会导致内存泄漏问题?
答案 0 :(得分:2)
你的processGrayFrame
是正确的,这就是你应该如何使用它。我认为问题是你没有传入限制范围内的x
和y
值。您对processGrayFrame
的呼叫未通过入境点。至少MatrixStartPointY + matrixHeight
肯定是出界的。
还要确保正确分配矩阵(分配时元素类型为uchar
- 我认为这将是CV_8UC1
,至少如果你有8位char
} S)。
在调试模式下运行OpenCV,它应该告诉你何时坐标超出范围。
答案 1 :(得分:0)
使用C ++接口时很难发生内存泄漏。实际上,你必须是专家才能做到这一点:)
这是一种误报,通常在Windows系统上发生(请参阅memory leak in opencv functions),或者在程序的其他部分发生泄漏。
为了确保它不是泄漏,您应该使用检漏仪对其进行分析。
答案 2 :(得分:0)
使用assert(0<=x&&x<m.cols&&0<=y&&y<m.rows)
宏来检查边界条件。 (如果设置了DEBUG标志或者您使用IDE处于调试模式,则检查仅出现在实际代码中。)
如果您没有克隆视频帧,也可能发生潜在的泄漏。
视频帧cv :: Mat(你可能来自cv::VideoCapture cap(0); cap>>frame;
)必须克隆出来。否则根据我的经验,你会不时泄漏,而不是每一帧。 (我想只有当缓冲区的位置发生变化时才会发生变化。)
因此解决方案为cap>>frame_raw; Mat frame = frame_raw.clone();
(我认为您实际上是致电frame
videoFrameInput
)。
REMARK:
我知道这不是重点,但你更熟悉opencv drawing functions(如果还没有这样做的话)
填充cv::line(mat, p1, p2, color,...)
,cv::rectangle(...)
,cv::ellipse(...)
和cv::floodFill(...)
只是为了填写。这些更有效,因为它们具有更高效的内存访问(不使用.at<>()
,也可以优化和并行化访问顺序)。