Add alpha channel to opencv Mat - c++

Using the cv::imread I was able to reading the RGB image to cv::Mat (as below)
Mat picture = imread(fileName, -1);
Instead of reading, I tried to create an RGB image using the following code :
Mat arr1 = Mat(9, 9, CV_8UC1, &data1);
Mat arr2 = Mat(9, 9, CV_8UC1, &data2);
Mat arr3 = Mat(9, 9, CV_8UC1, &data3);
Mat pic;
vector<Mat> mk(3);
mk.at(0)=(arr1);
mk.at(1)=(arr2);
mk.at(2)=(arr3);
merge(mk,pic);
Will the Mat picture and Mat pic be equal?
As cv::imread has a flag of '-1' which indicates that 'Return the loaded image as is (with alpha channel)'. Which I am not able to understand and how do I match 'pic' to 'picture'?(Not picture to pic)

-1 Flag in cv::imread indicates that image will be loaded as it is including the alpha channel if present. So, if your image file has alpha channel, your picture(Mat) will be a CV_8UC4 type of image while your pic(Mat) is a 3 channel image. Hence, they won't be same in some cases. But if your picture(Mat) has only 3 channels and its B, G, R channels have same data as data1, data2, data3 respectively then your 'picture' and 'pic' will be same.

Related

Loading an array of pixel values in OpenCV

I have a 32-bit integer array containing pixel values of a 3450x3450 image I want to create a Mat image with. Tried the following:
int *image_array;
image_array = (int *)malloc( 3450*3450*sizeof(int) );
memset( (char *)image_array, 0, sizeof(int)*3450*3450 );
image_array[0] = intensity_of_first_pixel;
...
image_array[11902499] = intensity_of_last_pixel;
Mat M(3450, 3450, CV_32FC1, image_array);
and upon displaying the image I get a black screen. I should also note the array contains a 16-bit grayscale image.
I guess you should try to convert the input image, which I assume is in RGB[A] format using:
cv::Mat m(3450, 3450, CV_8UC1, image_array) // For GRAY image
cv::Mat m(3450, 3450, CV_8UC3, image_array) // For RGB image
cv::Mat m(3450, 3450, CV_8UC4, image_array) // For RGBA image

Opencv C++ grayscale image black pixeled result (when replacing image values)

I'm new in opencv and I had this problem...
Given the following Mat type (globally declarated)
Mat src_gray;
Mat dst;
I have dst being a zero grayscale Mat with this initialization
dst=Mat::zeros(src_gray.size(), CV_BGR2GRAY);
It seems I can't edit the pixels on the dst image (when I use imwrite, it gives me a black image as if I hadn't done anything).
This is the code I currently have:
for(int i=0;i<=dst.cols;i++)
for(int j=0;j<=dst.rows;j++)
{
dst.at<uchar>(j,i)=255;
}
imwrite( "img_res.png", dst );
The result Image has the dimensions it's supposed to have, but it is a black pixeled picture, shouldn't it be a white pixeled Image?
I don't know if it is relevant if I mention that I have 3 global Mats
Mat image;
Mat src_gray;
Mat dst;
Which are initialized this way:
image = imread( argv[1], 1 );
cvtColor( image, src_gray, CV_BGR2GRAY );
Then, I release them as:
image.release();
dst.release();
src_gray.release();
The other problem I get is that when I release the Mats (during execution), I get the "Segmentation fault (core dumped)" error. (I code from Linux Ubuntu distri)
Try:
dst=Mat::zeros(src_gray.size(), CV_8UC1);
When you use CV_BGR2GRAY, you are creating a Mat with 3 color channels, then, it's not possible to assign a number when you have an array of numbers (B,G,R).
With CV_8UC1, you create a Mat with 1 color channel of uchar then it should works with:
dst.at<uchar>(j,i)=255;

Create a transparent image in opencv

I am trying to rotate an image in x, y and z axis as in this.
The image should not be cropped while rotating So I am doing this
Mat src = imread("path");
int diagonal = (int)sqrt(src.cols*src.cols+src.rows*src.rows);
int newWidth = diagonal;
int newHeight =diagonal;
Mat targetMat(newWidth, newHeight, src.type());
I am creating a bigger image targetMat. The input image is a png image.
But I want this image as a transparent image. So I tried this
Mat targetMat(newWidth, newHeight, src.type(), cv::Scalar(0,0,0,0));
But the output image was
What I need is (Transparent image is here)
So what change do I have to do?
The problem is, that your input image is type CV_8UC3 but you need CV_8UC4 to use the alpha channel. So try Mat targetMat(newHeight, newWidth, CV_8UC4, cv::Scalar(0,0,0,0)); or cvtColor of src before creation of new mat
To use your original image, there are two possibilities:
use cv::cvtColor(src, src, CV_BGR2BGRA) (and adjust later code to use a 4 channel matrix - cv::Vec4b instead of cv::Vec3b etc)
if your input file is a .png with alpha channel you can use the CV_LOAD_IMAGE_ANYDEPTH (hope this is the right one) flag to load it as a CV_xxC4 image (might be 16 bit too) and to use the original alpha values.

BGR to YCrCb resulting in gray images in OpenCV

I'm converting a BGR image to YCrCb and saving it in the disk; however, the output images are gray, how can I save the images to disk with color?
Here is just an example of how my code looks like:
Mat img = imread("...");
Mat img2;
cvtColor(img, img2, CV_BGR2YCrCb);
vector<Mat> planes;
split(imgColorConverted, planes);
imwrite(".../planes1.jpg", planes[0]);
imwrite(".../planes2.jpg", planes[1]);
imwrite(".../planes3.jpg", planes[2]);
When I open the saved images, it is gray. Is it possible to save the images as the following example that I found on Wikipedia (Wikipedia - YCbCr)?:
Thank you!
In you case, you save 1 channel pictures, so it's gray. In fact, what you should do is:
Mat img = imread("...");
Mat img2;
cvtColor(img, img2, CV_BGR2YCrCb);
vector<Mat> planes;
split(imgColorConverted, planes);
Mat* planes2 = new Mat[3];
Mat emptyMat(planes[0].size(), planes[0].type(), Scalar(0));
Mat Cr, Cb;
imwrite(".../planes1.jpg", planes[0]);
// Set Cr channel on R channel
planes2[0] = emptyMat;
planes2[1] = emptyMat;
planes2[2] = planes[1];
merge(planes2, 3, Cr);
imwrite(".../planes2.jpg", Cr);
// Set Cb channel on B channel
planes2[0] = planes[2];
planes2[1] = emptyMat;
planes2[2] = emptyMat;
merge(planes2, 3, Cb);
imwrite(".../planes3.jpg", Cb);

Canny edge detection - grayscale images always coming up as 3-channel, unusable?

I am working through the book "Learning OpenCV" from the O'Reilly series and am trying to perform a canny edge detection sample.
Any grayscale image I choose seems to come up as having 3 channels, and to the best of my knowledge, canny only works with single channel images, so this always fails. I am even using the images provided by OpenCV.
Here is my code..
IplImage* doCanny(IplImage* in, double lowThresh, double highThresh, double aperture)
{
if(in->nChannels != 1)
return(0); //canny only handles gray scale images
IplImage* out = cvCreateImage(cvSize(in->width, in->height), IPL_DEPTH_8U, 1);
cvCanny(in, out, lowThresh, highThresh, aperture);
return(out);
};
IplImage* img = cvLoadImage("someGrayscaleImage.jpg");
IplImage* out = doCanny(img, 10, 100, 3);
Why might this always give me 3-channel images? How can I solve this?
You can use this method with another parameter
IplImage* cvLoadImage(const char* filename, int iscolor=CV_LOAD_IMAGE_COLOR)
#define CV_LOAD_IMAGE_COLOR 1
#define CV_LOAD_IMAGE_GRAYSCALE 0
#define CV_LOAD_IMAGE_UNCHANGED -1
The default parameter is load image with color. What you have to do is to load it with grayscale
Here is an example
cvLoadImage("yourimage.jpg", CV_LOAD_IMAGE_GRAYSCALE);
Here is the detail explanation for that method. You can look at here for more details:
Open CV 2.0 References
scolor – Specific color type of the loaded image: if $ > 0 $, the loaded image is forced to be a 3-channel color image; if 0, the loaded image is forced to be grayscale; if $ < 0 $, the loaded image will be loaded as is (note that in the current implementation the alpha channel, if any, is stripped from the output image, e.g. 4-channel RGBA image will be loaded as RGB).