Opencv - Overlay image without cvAddWeighted - c++

there are plenty of tutorials showing how to blend two images in opencv:
http://opencv.itseez.com/doc/tutorials/core/adding_images/adding_images.html
http://aishack.in/tutorials/transparent-image-overlays-in-opencv/
But all of them are based on this equation:
opencv blending http://opencv.itseez.com/_images/math/afeb868ed1632ace1fe886b5bfbb6fd933b742b8.png
which means that I will be combining two images by averaging them and consequently I'll be loosing intensity on both images.
For instance, let alpha = 0.5, f0(x) = 255, and f1(x) = 0. After applying this equation, the result image g(x) = 127. That is not what I need. The first image should remain unchanged. And the transparency must be applied in the second one.
My problem is:
the first image f0(x) should not be changed and an alpha should be applied to the second image f1(x) when it overlays the first image f0(x).
I cannot figure out how to do this. Any help?

Unfortunately, alpha channels are not supported by OpenCV. From the imread documentation:
Note that in the current implementation the alpha channel, if any, is stripped from the output image. For example, a 4-channel RGBA image is loaded as RGB if flags > 0.
See this SO post for a possible work around using imagemagick.
Hope that is helpful!

Related

ValueError: operands could not be broadcast together with shapes (400,400,3) (400,400)

I am using pyshearlab package to denoise image.The function expects an image shape of equal size.After the code is executed denoising is ok for some images
but some images generates an error like this.
ValueError: operands could not be broadcast together with shapes (400,400,3) (400,400).
so i i printed the shape of the image using img.size and it gives (400,400,3)
My question is,, is it possible to eliminate the third parameter from the image.
someone please help me.
I am using this for image denoising transformations.There are many toolkits available for image transformations in matlab.Is there any packages to do contourlet denoising,curvelet denoising,bandlet denoising etc in python.
When you have an image array of shape (400, 400, 3) in numpy that means that your image has a height and width of 400x400 and 3 channels.
Most of the time that would be Red, Green and Blue. Your other image with shape (400, 400) only has one channel. So these images won't work together nicely.
You have several options here. It really depends on what your function does with the images and what your output needs to be.
You could split the 3-channel image into separate channels and process them independently.
channel1 = image[:, :, 0]
channel2 = image[:, :, 1]
channel3 = image[:, :, 2]
And then merge them later
image = np.dstack((channel1, channel2, channel3))
Or if you are sure that you do not need all channels, in case of a greyscale image f. e. all channels might have the same values, you could drop two and only keep one.
Or you can bump your one channel image up to three channels so that they have the same dimensions (using np.dstack as well).

Multiply Images In OpenCv & Apply Laplacian Filter On It

In my previous question here's the link. According to the answer I have obtained the desired image which is white flood filled.
Now after applying the morphological operation of erosion on the white flood filled image, I get the new masked image.
Your answer helped a lot. Now what I am trying to do is that I am multiplying the new masked image with the original grayscaled image in order to get the veins pattern. But it gives me the same image as result which I get after performing erosion on the white flood filled image. After completing this step I have to apply the Laplacian function to get the veins pattern. I am attaching the original image and the result image that I want. I hope you will look into the matter.
Original Image.
Result Image.
If I am right in understanding you, you only want to extract the veins from the grayscale hand image, right? To do something like this, you would obviously multiply both of them as,
finalimg = grayimg * veinmask;
If you have done the above I think it would be more helpful to post a portion of your code so experts here might be able to point out whats wrong, also the output image that you're getting, and the one you want would also help.
I hope I understand you correctly. You have a gray scale image showing a hand (first image in your question)
You create a mask image that looks like the second image you posted.
Multiplication of both results in the mask image?
If that is the case check your values. If you work within a byte image your mask image must contain values 0 and 1, not 0 and 255 as the multiplication results for non-zero mask pixels otherwise exceed 255!

OpenCV HSV weird converted

I am working on project what detect hematoma from skin. I am having issue with color after convertion from RGB to HSV. My algorithm detect hematoma by its color.
With some images I have good results like here:
Original img: http://imgur.com/WHiOWdj
Result img: http://imgur.com/PujbnHa
But with some images i have bad result like this:
Original img: http://imgur.com/OshB99r
Result img: http://imgur.com/CuNzAId
The same original image after convertion to HSV: http://imgur.com/lkVwtCs
Do you have any ideas how to fix it?
Thanks
Looking at your result image I think that you are only using the H channel of the original image in your algorithm. The false positive detection can inherit from that the some part of the healty skin has quite the same H value than the hematoma has. You can see on the qrey-scale image of H channel that both parts have similar values:
The difference between the two parts is the saturation value. On the following image you can see the S channel of the original image and it shows perfectly that at the hematoma the saturation is much higher than at other the part of the arm:
This was expected because the hematoma has much stronger color than the healty skin has.
So, I suggest you to use both H and S channel in your algorithm that is you have to take into account only that parts of H image where the S image contains high saturation values. A possible and simple solution to do that is that you binarize both H and S images and with an AND operation you can execute this filtering:
H image after binarisation:
S image after binarisation:
Image after H&S operation:
You can see that on the result image only the hematoma part is white (except some noise but you can eliminate easily, for example by size or by morphological filtering).
EDIT
Important to note that binarization is one of most important (and sometimes also very complicated) step in the object detection algorithms namely binarization is the first highlight of the objects to detect.
If the the external conditions (lighting, color of objects etc.) do not change significantly from image to image you can use fix binaraziation thresholds. If this constant environment can not be issured you have to use more complicated methods. There are a lot of possibilies you can use, here you can read some examples:
Wikipedia - Thresholding
Wikipedia - Balanced histogram thresholding
Several solutions are based on the histogram analysis: on the histograms with objects there are always more local maximums which positions can vary depend on the environment and if you find them you can adapt the binarization threshold easily.
For example the histogram of the H channel of the original image is the following:
The first maximum belongs to the background, the second to the skin and the last to the hematome. It can be supposed that these 3 thresholds can be found in each image only their positions vary depend on the lighting or on other conditions. To put a threshold between the 2nd and the 3rd local maximum it can be a good choice to highlight the hematome.
Finally I offer you the read the following articel about thresholding in OpenCV:
OpenCV - Thresholding

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).

Range of HSV values to sample an Image as done by adobe

I have an image as shown in the inset. I sampled it in Adobe Photoshop using the blue color as the image shows. The sampled image is shown in gray-scale on the left.
I know that openCV provides a similar method to sample images that is the inRange() function. How can I find out the range of HSV values that Adobe checked for to sample my image. Since the resultant image is pretty much what I want and I am not able to determine the range myself It would be a great help if some one could guide me for the same.
You can convert your image in HSV with cv::cvtColor(...) here the documentation
Then accordingly to Wikipedia the blue is near to 240° of the HUE channel of your image.
You can set something like maxHue = 270 and a minHue = 180 or other values to scan your image.
Maybe you should set a minSaturation and a minValue to avoid the black and white.
To find the best ranges you can link them with some sliders in a Qt GUI and change them until you get the same result as photoshop...