目标和问题
我正在尝试使用 OpenCV 3.4.1 动态处理视频文件,方法是抓取每一帧,转换为灰度,然后对其进行 Canny 边缘检测。为了显示图像(也可以即时显示),我创建了一个带有 3 个额外标题的 Mat 类,其宽度是原始帧的三倍。3 个额外的标题代表我想在合成中显示的图像,并位于合成的第 1、第 2 和第 3 个水平段。
然而,经过图像处理后,合成图像的显示并不像预期的那样:第一段(原始帧应该在的位置)是完全黑色的,而其他段(处理后的图像)显示良好。另一方面,如果我在单独的窗口中一个一个地显示 ROI,则所有图像看起来都很好。
这些是我试图克服这个问题的事情:
- 使用 .copyTo 将数据实际复制到适当的图像段中。结果是一样的。
- 我将 Canny 图像放入 compOrigPart ROI,它确实显示在第一段中,因此 ROI 的定义没有问题。
- 将合成定义为三通道图像
- 在循环中将其转换为灰度
- 将处理后的图像放入其中
- 转换回 BGR
- 把原件放进去。
这一次,整个复合材料都是黑色的,什么也没显示。
- 根据gameon67的建议,我也尝试创建一个namedWindow,但这也无济于事。
代码:
int main() {
cv::VideoCapture vid("./Vid.avi");
if (!vid.isOpened()) return -1;
int frameWidth = vid.get(cv::CAP_PROP_FRAME_WIDTH);
int frameHeight = vid.get(cv::CAP_PROP_FRAME_HEIGHT);
int frameFormat = vid.get(cv::CAP_PROP_FORMAT);
cv::Scalar fontColor(250, 250, 250);
cv::Point textPos(20, 20);
cv::Mat frame;
cv::Mat compositeFrame(frameHeight, frameWidth*3, frameFormat);
cv::Mat compOrigPart(compositeFrame, cv::Range(0, frameHeight), cv::Range(0, frameWidth));
cv::Mat compBwPart(compositeFrame, cv::Range(0, frameHeight), cv::Range(frameWidth, frameWidth*2));
cv::Mat compEdgePart(compositeFrame, cv::Range(0, frameHeight), cv::Range(frameWidth*2, frameWidth*3));
while (vid.read(frame)) {
if (frame.empty()) break;
cv::cvtColor(frame, compBwPart, cv::COLOR_BGR2GRAY);
cv::Canny(compBwPart, compEdgePart, 100, 150);
compOrigPart = frame;
cv::putText(compOrigPart, "Original", textPos, cv::FONT_HERSHEY_PLAIN, 1, fontColor);
cv::putText(compBwPart, "GrayScale", textPos, cv::FONT_HERSHEY_PLAIN, 1, fontColor);
cv::putText(compEdgePart, "Canny edge detection", textPos, cv::FONT_HERSHEY_PLAIN, 1, fontColor);
cv::imshow("Composite of Original, BW and Canny frames", compositeFrame);
cv::imshow("Original", compOrigPart);
cv::imshow("BW", compBwPart);
cv::imshow("Canny", compEdgePart);
cv::waitKey(33);
}
}
问题
- 为什么我不能在单个窗口中显示整个合成图像,而单独显示它们是可以的?
- 这些显示器有什么区别?数据显然在那里,如单独的窗口所证明的那样。
- 为什么只有原始框架行为异常?