opencv background subtraction get color objects - c++

I've used below tutorial to do background subtraction,
http://docs.opencv.org/master/d1/dc5/tutorial_background_subtraction.html#gsc.tab=0
But using pMOG2->apply( frame, fgMaskMOG2 ) method return output as a binary image.
Is there any method to get only color objects after removing the background or get color image using binary image?

One thing you can do is to use the binary image as a mask for coping the objects from the color image into another image:
// create an image like frame but initialized to zeros
cv::Mat colorForeground = cv::Mat::zeros(frame.size(), frame.type());
// copy color objects into the new image using mask
frame.copyTo(colorForeground, fgMaskMOG2);
Now, in colorForeground, you can see the objects in color.

Related

Loading & Saving Bitmap Images In OpenCV (OpenCV Version = 3.1.0)

My problem is simple at least as I see, or how I feel about it.
I tried to load and write Bitmap images with OpenCV in C++ and got sucessed in it, my problem is about the way the image is loaded and written.
Here is the thing: I working on 256-color palette (8bpp), trying to edit or add somethings on it, and then I write it or you can say I save it.
The problem is that the color palette before and after loading the image is not the same.
It seems like OpenCV is not just load the image but also change the palette color, in my case it is changed to RGB color (24bpp) which cause of an output image with size 3 x original image size after I saved the loaded image.
My question is there a way to load it or write without changing image color palette? if not possible, is there a way to write it with specific color palette? so I can specify it to 256-color palette (8bpp), if not possible either any possible converter will be good (from RGB color (24bpp) to 256-color palette (8bpp)).
Here is my code to load and write the Bitmap image:
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
int main()
{
Mat BitImage = imread("BitImage_Intput.bmp", -1); // -1 To load image as it is (without changing) but not working.
imwrite("BitImage_Output.bmp", BitImage); // To write or save the image.
waitKey(0);
return 0;
}
I found this function, imread("BitImage_Intput.bmp", CV_8UC1);, It does the job in a side but ruins it on the other side, the color palette not changed but I got a GRAYSCALE image (All colors except white and black are removed or replaced).
The 256-color palette (8bpp) Bitmap Image
The RGB color (24bpp) Bitmap Image
The GRAYSCALE (8bpp) Bitmap Image

OpenCV function to merge Mat's except for black/transparent pixels

I have a Mat containing text with a black background and a Mat containing a background. I want to merge the 2 Mat's so the text sits ontop of the background. Both Mats are BGR (CV_8UC3) and the same size (cols and rows).
Whats the OpenCV way of doing this?
I'm aware of a couple of functions but |= and += are changing the text colour and addWeighted() only works if I want one image to be slightly transparent. I just want to do a complete merge of the two (except not the black pixels in the text image). I'm looking for an OpenCV function rather than pixel editting myself, well a LUT would be good if thats an option.
Try this:
sourceText = yourTextImage;
sourceBackground = yourBackgroundImage;
cv::Mat textTransparent;
cv::inRange(sourceText, cv::Scalar(0,0,0), cv::Scalar(0,0,0), textTransparent);
cv::imshow("transparent pixel", textTransparent); // this should show all the transparent pixel as being white. If that's not the case, adjust the range.
std::cout << "is the transparency mask ok? Press any key with openCV window focus." << std::endl;
cv::Mat result = sourceBackground.clone();
sourceText.copyTo(sourceBackground, 255-textTransparent); // copy pixels, using the created mask.
instead you could copy the transparent pixels from the sourceBackground to the sourceText which is a bit faster because you don't need the 255-textTransparent...
Could not test the code, please tell me if there are bugs.

Cannot load and overlay transparent image in OpenCV

I have transparentGUI.png image with transparent background - in GIMP it looks like that:
When I load it in OpenCV by Mat imgColorPanel = imread("transparentGUI.png", -1); and then display it by imshow("widok", imgColorPanel);, i can see this image with white background (which is wrong, because it should be transparent):
Eventually I want to overlay this image (with it's transparent background) on camera captured image. If I do it using other image, which has background (so it's not transparent) - then it's correctly overlayed.
However, when I want to overlay transparentGUI.png image on captured camera image by addWeighted(imgColorPanel, 0.8, imgOriginal, 0.6, 0, imgOriginal);, program crashes with console error:
as well as Debugging error:
Everything works unless I want to load and display image with transparent background. I assume it may be a conflict with imgOriginal, because it's in HSV - I am building program for object detection by HSV colors, so i cannot change it. Is it ok with overlaing HSV image with BGRA image (the transparent one)? Default color range of OpenCV is BGR, so even camera capture image is converted to HSV, then I can overlay it by other image which is BGR - so, I think that something else must be a problem.
imgColorPanel and imgOriginal should have the same size. From your statement, imgColorPanel has 4 channels (RGBA). To make "addWeighted" work, imgOriginal should also have 4 channels, instead of 3 HSV channels.
For "imshow", I think it is just display issue, and you may print out the size of imgColorPanel to check if it has 4 channels.
You are having two different problems:
i can see this image with white background (which is wrong, because it
should be transparent)
well, it's not wrong because you can't see transparency anyway and there's no standard consensus on how it should be rendered independent of context. In the case of GIMP you do see something - the background of the context-window containing the image. In the case of HighGui you probably get a white-background simply because that's the nominal background in this case. The only way around this is to tell the program what exactly seeing transparency means in the context of your program. This might require using another GUI-system, depends on what you want to do.
program crashes with console error
as the error message says, the problem is that the images you are trying to overlay have a different size. A solution would be to first create a transparent base image of the desired size, e.g. like this:
cv::Mat imgColorPanel {imgOriginal.rows, imgOriginal.cols, CV_8UC4, cv::Scalar{0,0,0,0}};
and then load the panel from your image in the desired part of the base using a ROI (the image has to be smaller than the base of course..) e.g.:
cv::Mat panel {cv::imread("PATH/TO/FILE")};
cv::Rect roi {0,0,panel.rows,panel.cols}; // x,y,width,height
cv::Mat imRoi {imgColorPanel(roi)};
imRoi = panel.clone();

In open cv, how can i convert gray scale image back in to RGB image(color)

In open cv to remove background, using current frame and former frame, i applied absdiff function and created a difference image in gray scale. However, i would like to covert the gray scale image back in to RGB with actual color of the image, but i have no idea how to operate this back in.
I'm using C++.
Could any one knowledgeable of open cv help me?
You cannot covert the gray scale image back into RGB with actual color of the image again as coverting RGB to gray scale is a data-losing process.
Instead, as #MatsPetersson suggested, you can take the use of the grayscale image to create a mask, e.g. by further applying a thresholding process. Then you can easily get the ROI color image by:
cv::Mat dst;
src.copyTo(dst, mask);

Transparent pixels in OpenCV C++ (when using GrabCut)

I am using OpenCV 's implementation of GrabCut in order to remove the background from images. But for now the new background is black. Is there any way to make it transparent?
For now this part of the code looks like this:
Mat binMask( image.size(), CV_8UC1 );
binMask = mask & 1;
image.copyTo( result, binMask );
Can I somehow fill the binMask with transparent pixels?
I've read some tutorials for overlaying images, but I don't need a transparent image in front of my picture but behind.
I hope someone could help.
Many thanks!
Since you are using a 8UC1 image type, it's not possible to have transparent pixels.
These are allowed only if you have an alpha channel, with alpha set to 0: you must use a 4-channel image (3 for colors, 1 for alpha channel). The alpha channel is supported in file formats such as PNG, but not in JPG.
In case of masking, you don't need by the way the usage of transparent pixels, since the black ones actually correspond to 0 and they don't influence the result when you're blending two images (addWeighted for example, or also in case of bitwise_or operation).