Why are spots left when converting an RGBA image to RGB? - libpng

I converted a png (RGBA) to jpeg (RGB) using libpng to decode the png file and applying png_set_strip_alpha to ignore alpha channels. But after conversion the output image has many spots. I think the reason is that the original image has areas whose alpha was 0, which hides the pixel regardless of its RGB value. And when I strip alpha(ie set alpha = 1), the pixel shows. So I think just using png_set_strip_alpha is not the right solution. Should I write a method myself, or is there already a way to achieve this in libpng?

There is no method for that. If you drop alpha channel libpng will give you raw RGB channels and this will "uncover" colors that were previously invisible.
You should load RGBA image and convert it to RGB yourself. The simplest way is to multiply RGB values by alpha.
This will convert RGBA bitmap to RGB in-place:
for(int i=0; i < width*height; i++) {
int r = bitmap[i*4+0],
g = bitmap[i*4+1],
b = bitmap[i*4+2],
a = bitmap[i*4+3];
bitmap[i*3+0] = r * a / 255;
bitmap[i*3+1] = g * a / 255;
bitmap[i*3+2] = b * a / 255;
}

Related

Convert color image into grey in opencv without CV_RGB2GRAY

I want to convert colorBGR image into grey scale in opencv without using direct command CV_RGB2GRAY. Here I uploaded my code which gives me a bluish color of the image which is not a proper grey output image. Please check the below code and tell me where I m going wrong or you can give me another solution to convert the color image into grey output image without CV_RGB2GRAY.
Thanks in advance.
Mat image=imread("Desktop\\Sample input\\ip1.png");
Mat grey( image.rows,image.cols, CV_8UC3);
for(int i=0;i<image.rows;i++)
{
for(int j=0;j<image.cols;j++)
{
int blue = image.at<Vec3b>(i,j)[0];
int green = image.at<Vec3b>(i,j)[1];
int red = image.at<Vec3b>(i,j)[2];
grey.at<Vec3b>(i,j) = 0.114*blue+0.587*green+ 0.299*red ;
}
}
imshow("grey image",grey);
If you intend to convert the image which you are taking by imread() functions, you can take the image as input as a grayscale image directly by
Mat image = imread("Desktop\\Sample input\\ip1.png",CV_LOAD_IMAGE_GRAYSCALE);
or, by
Mat image = imread("Desktop\\Sample input\\ip1.png",0);
It is because CV_LOAD_IMAGE_GRAYSCALE corresponds to the constant 0. And when in imread() function gets this argument zero, it will load an image with intensity one.
And if want to convert any image to grayscale then the out image image should like
Mat grey = Mat::zeros(src_image.rows, src_image.cols, CV_8UC1);
as grayscale image is of only one channel and then you can convert the image like this:
for(int i=0;i<image.rows;i++)
{
for(int j=0;j<image.cols;j++)
{
int blue = image.at<Vec3b>(i,j)[0];
int green = image.at<Vec3b>(i,j)[1];
int red = image.at<Vec3b>(i,j)[2];
grey.at<uchar>(i, j) = (uchar) (0.114*blue + 0.587*green + 0.299*red);
}
}
It will give you the grayscale image.
In your code, the grey Mat has 3 channels. For a grayscale image you only need 1 channel (8UC1).
Also, when you are writing the values in the grayscale image, you need to use uchar instead of Vec3b because each pixel in the grayscale image is only made up of one unsigned char value, not a vector of 3 values.
So, you need to replace these lines:
Mat grey(image.rows, image.cols, CV_8UC1);
and
grey.at<uchar>(i, j) = 0.114*blue + 0.587*green + 0.299*red;

how to superimpose two images?

I have a visualization output of gabor filter with 12 different orientations.I want to superimpose the vizualization image on my image of retina for vessel extraction.How do i do it?I have tried the below method.is there any other method to perform superimposition of images in matlab.
here is my code
I = getimage();
I=I(:,:,2);
lambda = 8;
theta = 0;
psi = [0 pi/2];
gamma = 0.5;
bw = 1;
N = 2;
img_in = im2double(I);
%img_in(:,:,2:3) = []; % discard redundant channels, it's gray anyway
img_out = zeros(size(img_in,1), size(img_in,2), N);
for n=1:N
gb = gabor_fn(bw,gamma,psi(1),lambda,theta)...
+ 1i * gabor_fn(bw,gamma,psi(2),lambda,theta);
% gb is the n-th gabor filter
img_out(:,:,n) = imfilter(img_in, gb, 'symmetric');
% filter output to the n-th channel
%theta = theta + 2*pi/N
%figure;
%imshow(img_out(:,:,n));
imshow(img_in); hold on;
h = imagesc(img_out(:,:,n)); % here i am getting error saying CDATA must be size[M*N]
set( h, 'AlphaData', .5 ); % .5 transparency
figure;
imshow(h);
theta = 15 * n; % next orientation
end
this is my original image
this is my visualized image got by gabor filter using orientation
this is the kind/type of image i have to get with respect to visualisation .i.e i have to impose visualized image on my original image and i have to get this type of image
With the information you have provided, my understanding is you want the third/final image to be an overlay on top of the first/initial image. I do things like this when using segmentation to detect hemorrhaging in MRI images of the brain.
First, let's set up some defintions:
I_src = source/original image
I_out = output/final image
Now, make a copy of I_src and make it a color image rather than grayscale.
I_hybrid = I_src
colorIm = gray2rgb(I_src)
Let's assume both I_src and I_out are the same visual dimensions (ie: width, height), and that I_out is strictly black-and-white (ie: monochrome). Now, we can use I_out as a mask template for alpha channel adjustments in the resulting image. This is where it gets fun.
BLACK=0;
WHITE=1;
[length width] = size(I_out);
for i = 1:1:length
for j = 1:1:width
if (I_out(i,j) == WHITE)
I_hybrid(i,j) = I_hybrid(i,j) + [0.25 0 0]a;
end
end
This will result in you getting your original image with the blood vessels in the eye being slightly brighter and tinted red. You now have a beautiful composite of your original image with the desired features highlighted, but not overwritten (ie: you can undo the highlighting by subtracting the original color vector).
I will include an example of what the output would look like, but it's noisy because I had to create it in GIMP as I don't have Matlab installed right now. The results will be similar, but yours would be much cleaner and prettier.
Please let me know how this goes.
References
"Converting Images from Grayscale to Color" http://blogs.mathworks.com/pick/2012/11/25/converting-images-from-grayscale-to-color/

how to separate BGR components of a pixel in color image using openCV

Since each pixel memory contains 8 bit for each component Blue,Green and Red. So how can I separate these components from Image or Image Matrix. As
int Blue = f(Image(X,y));// (x,y) = Coordinate of a pixel of Image
similarly, for red and green.
So what should be function f and 2D matrix Image;
Thanks in advance
First off, you must go through the basics of OpenCV and turn your attention towards other parts of image processing. What you ask for is pretty basic and assuming you will be using OpenCV 2.1 and higher,
cv::Mat img = Read the image off the disk or do something to fill the image.
To access the RGB values
img.at<cv::Vec3b>(x,y);
But would give the values in reverse that is BGR. So make sure you note this.
Basically a cv::Vec3b type that is accessed.
img.at<cv::Vec3b>(x,y)[0];//B
img.at<cv::Vec3b>(x,y)[1];//G
img.at<cv::Vec3b>(x,y)[2];//R
or
Vec3f pixel = img.at<Vec3f>(x, y);
int b = pixel[0];
int g = pixel[1];
int r = pixel[2];
Now onto splitting the image into RGB channels you can use the following
Now down to primitive C style of OpenCV (There C and C++ style supported)
You can use the cvSplit function
IplImage* rgb = cvLoatImage("C://MyImage.bmp");
//now create three single channel images for the channel separation
IplImage* r = cvCreateImage( cvGetSize(rgb), rgb->depth,1 );
IplImage* g = cvCreateImage( cvGetSize(rgb), rgb->depth,1 );
IplImage* b = cvCreateImage( cvGetSize(rgb), rgb->depth,1 );
cvSplit(rgb,b,g,r,NULL);
OpenCV 2 CookBook Is one of the best books on OpenCV. Will help you alot.

How to change saturation values with opencv?

In order to add constant value to each pixel's saturation value, I do this in double loops. I wonder if there is any simpler and faster command achieving this.
Mat img(200, 300, CV_8UC1);
Mat saturated;
double saturation = 10;
double scale = 1;
// what it does here is dst = (uchar) ((double)src*scale+saturation);
img.convertTo(saturated, CV_8UC1, scale, saturation);
EDIT
If by saturation, you mean the S channel in a HSV image, you need to separe your image in three channels with split(), apply the saturation correction to the S channel, and then put them together with merge().
For the experiments I attempted, the alternative method of splitting hsv values, adjusting the individual channels and then doing a merge gave a better performance. Below is what worked for me many times faster as compared to looping through pixels:
(h, s, v) = cv2.split(imghsv)
s = s*satadj
s = np.clip(s,0,255)
imghsv = cv2.merge([h,s,v])
Note that I had converted the values to float32 during BGR2HSV transformation to avoid negative values during saturation transformation to due uint8 (default) overflow:
imghsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV).astype("float32")
And converted it back to default uint8 after my saturation adjustment:
imgrgb = cv2.cvtColor(imghsv.astype("uint8"), cv2.COLOR_HSV2BGR)

How to convert captured bitmap to 8 bit image as gray scale?

I am trying to convert the camera captured image to 8 bit image. And that should be grayscale image.
I searched in forums but could able to find the way to convert to 8 bit image.
Any help or suggestion will be help ful to me.
Thanks....
You have given too little information. First of all, what is the image format your camera delivers? Is it some RAW format, jpeg, or what else?
Doing it programmatically (using C for the example):
The best way to go was to use some image loading library (e.g. SDL_image), and load the image into memory, uncompressed RGB being the target format. Once you have an uncompressed RGB image format, you could do something like
// bufPtr points to the start of the memory containing the bitmap
typedef unsigned char byte;
struct rgb { byte red, green blue; } * colorPtr = bufPtr;
for (int i = 0; i < bufSize; i++, bufPtr++) {
byte gray = (unsigned char) (((float) bufPtr->red * 0.3f +
(float) bufPtr->green * 0.59f +
(float) bufPtr->blue * 0.11f)) / 3.0f * 255.0f + 0.5f);
bufPtr->red = bufPtr->green = bufPtr->blue = gray;
}
If you don't want to code, you could e.g. use GIMP, load your image and apply desaturate from the color menu. You can install the ufraw plugin for GIMP to load images in RAW format in it. If you want to store the entire color information in 8 bits (and not use 8 bits per color channel), there is another option in GIMP to decrease the color depth.

Resources