使用 OpenCV 可以实现画中画吗?

发布于 2024-11-15 17:23:26 字数 534 浏览 5 评论 0原文

我想在较大图像的顶部添加较小的图像(最终用于视频源上的画中画)。我可以通过迭代大图像中的相关数据属性并添加小图像中的像素来完成此操作。但有没有更简单、更简洁的方法呢?我正在使用EMGU。

我的想法是在与小图像大小相同的大图像中定义 ROI。将大图像设置为等于小图像,然后简单地删除 ROI。即用伪代码:

Large.ROI = rectangle defined by small image;

Large = Small;

Large.ROI = Rectangle.Empty;

但是这不起作用,并且大图像不会改变。任何建议将不胜感激。

大图:
大图

小图:
小图片

期望的结果:
所需结果

I would like to add a smaller image on top of a larger image (eventually for PiP on a video feed). I can do it by iterating through the relevant data property in the large image and add the pixels from the small image. But is there a simpler and neater way? I'm using EMGU.

My idea was to define an ROI in the large image of the same size as the small image. Set the Large image equal to the small image and then simply remove the ROI. Ie in pseudo code:

Large.ROI = rectangle defined by small image;

Large = Small;

Large.ROI = Rectangle.Empty;

However this doesn't work and the large image doesn't change. Any suggestions would be much appreciated.

Large image:
Large Image

Small image:
Small Image

Desired result:
Desired Result

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

箜明 2024-11-22 17:23:26

如果您使用 C++ API,那么以下代码片段应该可以工作:

cv::Mat big;
cv::Mat small;

// Define roi area (it has small image dimensions). 
cv::Rect roi = cv::Rect(50,50, small.cols, small.rows);

// Take a sub-view of the large image
cv::Mat subView = big(roi); 

// Copy contents of the small image to large
small.copyTo(subView); 

注意不要超出大图像的尺寸。

If you using C++ API then the following code snippet should work:

cv::Mat big;
cv::Mat small;

// Define roi area (it has small image dimensions). 
cv::Rect roi = cv::Rect(50,50, small.cols, small.rows);

// Take a sub-view of the large image
cv::Mat subView = big(roi); 

// Copy contents of the small image to large
small.copyTo(subView); 

Take care to not go out of dimensions of big image.

埖埖迣鎅 2024-11-22 17:23:26

我不知道这是否有帮助,我没有使用过emgu。然而,这就是我能够使用 opencv 进行图像中图像的方式。

drawIntoArea(Mat &src, Mat &dst, int x, int y, int width, int height)
{
    Mat scaledSrc;
    // Destination image for the converted src image.
    Mat convertedSrc(src.rows,src.cols,CV_8UC3, Scalar(0,0,255));

    // Convert the src image into the correct destination image type
    // Could also use MixChannels here.
    // Expand to support range of image source types.
    if (src.type() != dst.type())
    {
        cvtColor(src, convertedSrc, CV_GRAY2RGB);
    }else{
        src.copyTo(convertedSrc);
    }

    // Resize the converted source image to the desired target width.
    resize(convertedSrc, scaledSrc,Size(width,height),1,1,INTER_AREA);

    // create a region of interest in the destination image to copy the newly sized and converted source image into.
    Mat ROI = dst(Rect(x, y, scaledSrc.cols, scaledSrc.rows));
    scaledSrc.copyTo(ROI);
}

I don't know if this will help, i haven't used emgu. However this was how i was able to do image in image with opencv.

drawIntoArea(Mat &src, Mat &dst, int x, int y, int width, int height)
{
    Mat scaledSrc;
    // Destination image for the converted src image.
    Mat convertedSrc(src.rows,src.cols,CV_8UC3, Scalar(0,0,255));

    // Convert the src image into the correct destination image type
    // Could also use MixChannels here.
    // Expand to support range of image source types.
    if (src.type() != dst.type())
    {
        cvtColor(src, convertedSrc, CV_GRAY2RGB);
    }else{
        src.copyTo(convertedSrc);
    }

    // Resize the converted source image to the desired target width.
    resize(convertedSrc, scaledSrc,Size(width,height),1,1,INTER_AREA);

    // create a region of interest in the destination image to copy the newly sized and converted source image into.
    Mat ROI = dst(Rect(x, y, scaledSrc.cols, scaledSrc.rows));
    scaledSrc.copyTo(ROI);
}
挥剑断情 2024-11-22 17:23:26

我在 EMGU 方面有很多经验。据我所知,您采用的方法是在大图像中显示子图像数据的唯一直接方法。您可能需要刷新较大的图像,这会产生擦除传输的数据并将较小的图像复制回来的固有效果。

虽然解决方案是可能的,但我认为该方法是有缺陷的。所需的处理时间将影响较大观看帧中任何图像的显示速率。

一种改进的方法是添加另一个控件。实际上,您的视频源窗口在背景中显示较大的图像,而在其顶部有一个较小的控件显示较小的图像。实际上,您可以根据需要拥有任意数量的这些较小的控件。实际上,您将在两个不同的控件(例如图像框)中显示两个图像或视频源。由于您拥有执行此操作的代码,因此您所要做的就是确保控件的显示顺序。

我假设您没有将输出编程到控制台窗口。如果您需要更多帮助,请随时询问。

至于评论 EMGU 是用 C# 编写的,虽然很欣赏您对不调用 EMGU OpenCV 的看法,但为什么不应该将其标记为面向 OpenCV 的问题。毕竟 EMGU 只是带有 ac# 包装器的 OpenCV 库。我发现 OpenCV 上的许多资源对 EMGU 很有用,反之亦然。

干杯
克里斯

I have a lot of experience with EMGU. As far as I am aware the method your employing is the only direct way of display the sub-image data within your large image. You would likely have to refresh your larger image which would have the inherent effect of wiping your transferred data and copy the smaller image back over.

While a solution is possible I think the method is flawed. The required processing time will effect the display rate of any image in the larger viewing frame.

An improved method would be to add another control. Effectively you have your video feed window showing your larger image in the background and a smaller control on-top of this displaying your smaller image. Effectively you could have as many of these smaller controls as you like. You will in effect be displaying two images or video feeds in two different controls (e.g. image boxes). As you have the code to do so all you will have to do is ensure the order of which your controls are displayed.

I have assumed you are not programming the output to a Console Window. If you need any more help please feel free to ask.

As for the comments EMGU is written in C# and while appreciate your view on not calling EMGU OpenCV why should it not be tagged as an OpenCV orientated question. After all EMGU is simply OpenCV library with a c# wrapper. I have found many resources on OpenCV useful for EMGU and vice versa.

Cheers
Chris

掐死时间 2024-11-22 17:23:26

根据 @BloodAxe 的回答,使用 EMGU 3.4 可以进行以下工作:

// Define roi area (it has small image dimensions). 
var ROI = new System.Drawing.Rectangle(100, 500, 200, 200)

// Take a sub-view of the large image
Mat subView = new Mat(bigImage, ROI);

// Copy contents of the small image to large
small.CopyTo(subView);

Based on @BloodAxe's answer, using EMGU 3.4 the following works:

// Define roi area (it has small image dimensions). 
var ROI = new System.Drawing.Rectangle(100, 500, 200, 200)

// Take a sub-view of the large image
Mat subView = new Mat(bigImage, ROI);

// Copy contents of the small image to large
small.CopyTo(subView);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文