Should I initialize a cv::Mat - c++

I have this code:
mapx.create(image.size(), CV_32FC1);
mapy.create(image.size(), CV_32FC1);
what is the values in the mapx and mapy after this? Are all data is zero?
what about this type of initialization:
cv::Mat mapx(image.size(), CV_32FC1);
Do I need explicitly set the value of each element to zero?
How can I set the value of each element to say -1?

Data after create should be undefined. In fact, your are just allocating memory.
cv::Mat mapx(image.size(), CV_32FC1);
is exactly as
cv::Mat1f mapx(image.size());
and
cv::Mat mapy;
mapy.create(image.size(), CV_32FC1);
You can assign an initial value (e.g. -1) like this:
cv::Mat1f(images.size(), -1.f);
Regarding you main question Should I initialize a cv::Mat, the answer is that in general you don't need to. From OpenCV doc:
Instead of writing:
Mat color;
...
Mat gray(color.rows, color.cols, color.depth());
cvtColor(color, gray, CV_BGR2GRAY);
you can simply write:
Mat color;
...
Mat gray;
cvtColor(color, gray, CV_BGR2GRAY);

You can see the opencv documentation :
Mat::zeros
Mat::ones
Mat A = Mat::ones(100, 100, CV_8U)*3; // make 100x100 matrix filled with 3.
http://docs.opencv.org/modules/core/doc/basic_structures.html#mat-zeros
How can I set the value of each element to say -1?
I think something like that :
Mat A = Mat::ones(100, 100, CV_8U)*-1; // make 100x100 matrix filled with -1.

Related

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 mask from vector of point

What is the best way (performance point of view) to create a boolean mask cv::Mat from std::vector of cv::Point? In other words, I want a full black cv::Mat with white pixels for the points that are exist in some std::vector. Something like:
std::vector<cv::Point> points;
//Filling points
cv::Mat mask(100, 100, CV_8UC1, cv::Scalar(0));
for (const auto& pnt: points){
mask.ptr<uchar>(pnt.y)[pnt.x] = 255;
}
Is there a better(faster) approach? built-in one for example?

How to set all pixels of an OpenCV Mat to a specific value?

I have an image of type CV_8UC1. How can I set all pixel values to a specific value?
For grayscale image:
cv::Mat m(100, 100, CV_8UC1); //gray
m = Scalar(5); //used only Scalar.val[0]
or
cv::Mat m(100, 100, CV_8UC1); //gray
m.setTo(Scalar(5)); //used only Scalar.val[0]
or
Mat mat = Mat(100, 100, CV_8UC1, cv::Scalar(5));
For colored image (e.g. 3 channels)
cv::Mat m(100, 100, CV_8UC3); //3-channel
m = Scalar(5, 10, 15); //Scalar.val[0-2] used
or
cv::Mat m(100, 100, CV_8UC3); //3-channel
m.setTo(Scalar(5, 10, 15)); //Scalar.val[0-2] used
or
Mat mat = Mat(100, 100, CV_8UC3, cv::Scalar(5,10,15));
P.S.: Check out this thread if you further want to know how to set given channel of a cv::Mat to a given value efficiently without changing other channels.
The assignment operator for cv::Mat has been implemented to allow assignment of a cv::Scalar like this:
// Create a greyscale image
cv::Mat mat(cv::Size(cols, rows), CV_8UC1);
// Set all pixel values to 123
mat = cv::Scalar::all(123);
The documentation describes:
Mat& Mat::operator=(const Scalar& s)
s – Scalar assigned to each matrix element. The matrix size or type is not changed.
In another way you can use
Mat::setTo
Like
Mat src(480,640,CV_8UC1);
src.setTo(123); //assign 123

setImageROI using MAT image instead of Iplimage

cvSetImageROI(dst, cvRect(0, 0,img1->width,img1->height) );
cvCopy(img1,dst,NULL);
cvResetImageROI(dst);
I was using these commands to set image ROI but now i m using MAT object and these functions take only Iplimage as a parameter. Is there any similar command for Mat object?
thanks for any help
You can use the cv::Mat::operator() to get a reference to the selected image ROI.
Consider the following example where you want to perform Bitwise NOT operation on a specific image ROI. You would do something like this:
img = imread("image.jpg", CV_LOAD_IMAGE_COLOR);
int x = 20, y = 20, width = 50, height = 50;
cv::Rect roi_rect(x,y,width,height);
cv::Mat roi = img(roi_rect);
/* ROI data pointer points to a location in the same memory as img. i.e.
No separate memory is created for roi data */
cv::Mat complement;
cv::bitwise_not(roi,complement);
complement.copyTo(roi);
cv::imshow("Image",img);
cv::waitKey();
The example you provided can be done as follows:
cv::Mat roi = dst(cv::Rect(0, 0,img1.cols,img1.rows));
img1.copyTo(roi);
Yes, you have a few options, see the docs.
The easiest way is usually to use a cv::Rect to specifiy the ROI:
cv::Mat img1(...);
cv::Mat dst(...);
...
cv::Rect roi(0, 0, img1.cols, img1.rows);
img1.copyTo(dst(roi));

opencv: different ways to fill a cv::mat

I know that for fill a cv::Mat there is the nice cv::Mat::setTo method but I don't understand why I don't have the same effect with those pieces of code:
// build the mat
m = cv::Mat::zeros(size, CV_8UC3);
cv::cvtColor(m, m, CV_BGR2BGRA); // add alpha channel
/////////////////////////////////////////////////////////// this works
m.setTo( cv::Scalar(0,144,0,55) );
m = cv::Mat::zeros(size, CV_8UC3);
cv::cvtColor(m, m, CV_BGR2BGRA);
/////////////////////////////////////////////////////////// this does NOT work
m = m + cv::Scalar(0,144,0,55)
m = cv::Mat::ones(size, CV_8UC3);
cv::cvtColor(m, m, CV_BGR2BGRA);
/////////////////////////////////////////////////////////// this does NOT work
m = m.mul( cv::Scalar(0,144,0,55) );
m = cv::Mat::zeros(size, CV_8UC3);
cv::cvtColor(m, m, CV_BGR2BGRA);
/////////////////////////////////////////////////////////// this works too!
cv::rectangle(tracks,
cv::Rect(0, 0, tracks.cols, tracks.rows),
cv::Scalar(0,144,0,55),
-1);
PS: I'm displaying those mats as an OpenGL alpha texture
I guess "not work" means that the output is not the same as using setTo?
When transforming with cv::cvtColor, the alpha-channel is initialized to 255. If you add or multiply anything it will stay at 255.
Why do you use cv::cvtColor to transform instead of just using CV_8UC4 when creating the mat?
You can't use cv::Mat::ones for multichannel initialization. Only the first channel is set to 1 when using cv::Mat::ones. Use cv::Mat( x, y, CV_8UC3, CV_RGB(1,1,1) ).
For an aplha channel you need to use CV_8UC4, not CV_8UC3.