问题
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:
Small image:
Desired result:
回答1:
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.
回答2:
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);
}
回答3:
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
回答4:
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);
来源:https://stackoverflow.com/questions/6378543/is-picture-in-picture-possible-using-opencv