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:
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.
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);
}
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
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);
Related
I am using opencv in python to rotate an image and the original and the resulted images are differrent is somethings, I am doing my transformation through this part of code:
img = cv2.imread("image.tif")
new_image = cv2.getRotationMatrix2D((cols / 2, rows / 2), correction_angle, 1)
dst = cv2.warpAffine(img, new_image , (cols, rows))
cv2.imwrite("Rotated_image.tif", dst)
The original image's size is 1.7 Mb, The image's resolution is 300
dpi, and the color space is YCbCr.
The issue is that the resulting image with 12.5 Mb size, 96 dpi, the color space is RGB, and with compression "LZW"!
My question is that: Can I keep the main properties of the original image? and why rotating an image changes the size this way?
Note: The bit depth is 24 in both images.
Calling cv2.imread with only the name of the file uses the default value cv.IMREAD_COLOR for the second parameter, about which the documentation says:
If set, always convert image to the 3 channel BGR color image.
So, your image is always converted to RGB. You can try using cv.IMREAD_ANYCOLOR for the second parameter of imread, but I don't think you can use cv2.warpAffine on it trivially then.
The difference in the stored DPI information stems from the fact that you write the new image without any meta data. imwrite allows you to specify parameters (see here), but, unfortunately, they are not very well documented. I am not sure if this kind of data can be written out of the box with OpenCV.
Can I get pixel value of image and crop its black part. For instance, I have the this image:
.
And I want something like this
without the black part.
Any possible solution on how to do this? Any libraries/code?
I am using Objective C.
I have seen this solution to the similar question but I don't understand it in detail. Please kindly provide steps in detail. Thanks.
Probably the fastest way of doing this is iterating through the image and find the border pixels which are not black. Then redraw the image to a new context clipping the rect received by border pixels.
By border pixels I mean the left-most, top-most, bottom-most and right-most. You can find a way to get the raw RGBA buffer from the UIImage through which you may then iterate through width and height and set the border values when appropriate. That means for instance to get leftMostPixel you would first set it to some large value (or to the image width) and then in the iteration if the pixel is not black and if leftMostPixel > x then leftMostPixel = x.
Now that you have the 4 bounding values you can create a frame from it. To redraw just the target rectangle you may use various tools with contexts but probably the easiest is creating the view with size of bounding rect and put an image view with the size of the original image on it and create a screenshot of the view. The image view origin must be minus the origin of the bounded rect though (we put it offscreen a bit).
You may encounter some issues with the orientation of the image though. If the image will have some orientation other then up the raw data will not respect that. So you need to take that into account when creating the bounded rect... Or redraw the image first to make it oriented correctly... Or you can even create a sub buffer with RGBA data and create the CGImage from those data and applying the same orientation to the output UIImage as with input.
So after getting the bounds there are quite a few procedures. Some are slower, some take more memory, some are simply hard to code and have edge cases.
I am newbie to openCv, trying to analyze some code.
I know this line works fine and reduce destination by two but i want it to change to some other sizes, how can i change? Specifically "CV_GAUSSIAN_5x5"
cvPyrDown(frame, half_frame, CV_GAUSSIAN_5x5);
You cannot resize the image to any desired size by using pyrDown() because it will always resize your image by a factor of 2. Similar is the case with pyrUp().
If you want to resize your image to any desired size then you must use the resize()
cvResize(const CvArr* src, CvArr* dst, int interpolation=CV_INTER_LINEAR )
the detailed documentation about it is given here.
I have a series of images that I would look to loop through using iOS's [UIView startAnimating]. My trouble is that, when I exported the images, they all came standard in a 240x160 size, although only 50x50 contains the actual image, the rest being transparent parts that are just taking up space.
When I set the frame of the image automatically using image.size.width and image.size.height, iOS takes into images' original size of 240x160, so I am unable to get a frame that conforms to the actual parts of the image. I was wondering if there is a way using Illustrator or Photoshop, or any other graphics editing software for me to export the images based on their natural dimensions, and not a fixed dimension. Thanks!
I am a fan of vector graphics and thinks everything in the world should be vector ;-) so here is what you do in illustrator: file - document setup - edit artboards. Then click on the image, and the artboard should adjust to the exact size. You can of course have multiple artboards, or simply operate with one artboard and however-many images.
Is there a way to get the image dimension of an image that was just resized? What I'm foing is taking a file and fitting it to a 48x48 area (note, I said FIT, not scale.) Once that's done, I need to get the new image's dimension but I don't want to have to write it out to disk, then reading it back in to use. Is there a way to do it without that step?
$img = new Imagick('file.jpg');
$img->resizeImage(48,48,Imagick::FILTER_LANCZOS,1,TRUE);
// this is where I need to get the dimensions of the new image created above, unless it's a perfect square, only one side will be 48 pixels, the other could be less.
Thanks.