OpenCV affectation - c++

Why can't I do something like this:
cv::Mat img = imread("path/to/image1");
cv::Mat img2 = imread("path/to/image2");
img.ptr<uchar>(0,0) = img2.ptr<uchar>(0,0);
I get this message from VS : expression must be a modifiable lvalue
So instead I had to resort to doing something like this:
img.ptr<uchar>(0,0)[0] = img2.ptr<uchar>(0,0)[0];
And affect each channel, it doesn't bother me but I'd like to know why I can't do the other one.

The = operator would need to know what kind of image it was and would need complicated code for planar image types.
You can use the CV_IMAGE_ELEM macro

Related

Question about implicit (?) data conversion of cv::Vec3f to cv::Scalar during Mat initialization

Let's say we have this simple Mat
cv::Mat_<cv::Vec3f> image;
image.create(100,200);
image = cv::Vec3f(1.0, 0.0, 0.0);
My question would be why does this work properly by initializing the whole Mat?
If I had to guess, the following method is called (operator=):
https://docs.opencv.org/4.x/d3/d63/classcv_1_1Mat.html#aa5c947f7e449a4d856a4f3a87fcebd50
which only accepts a Scalar.
So I tried to search it out a bit more and I found out there could be the possibility of the Vec3f being data converted implicitly to a Scalar.
Also, I found this piece of code, which I am not entirely sure if it is contained within OpenCV:
static explicit operator Scalar (
Vec3b v
)
But: To the best of my knowledge, this only helps when you try to convert data types explicitly with something like:
Scalar s = (Scalar)point // where point is a cv::Vec3f
So what does actually happen in the initial initialization code? Does the Vec3f have to be data converted to the Scalar as I assumed? And if so, how exactly is it accomplished behind the scenes so that it actually works?

Boolean Not in OpenCV 3.1

I would like to know if there's a simple way of doing a boolean "not" operation on a cv::Mat. This does not work:
cv::Mat mat = cv::Mat::ones(3,3, CV_8U);
cv::Mat mat_not = !mat;
As such, is there an effective or simple way to do this? Should I resort to using something like this:
cv::Mat mat_not = mat < cv::Mat::ones(3,3,CV_8U);
Thanks a lot!
EDIT: I confused the "not" operator between MATLAB and C++ (since I'm translating the first one to the other). This works fine:
cv::Mat map2 = ~map1;
Edit: 12:30pm 7/20/2016
I see the op wants a regular NOT and I'm used to that being different for things like IDL and MatLab etc..
As #cxyzs7, #Cedric, and #Miki mentioned the operator in c++ is ~ so ...
mat = ~mat;
However if you ever want to do something else element wise (for example a bitwise) most of the time there's already a whole function for that. IE...
bitwise_not
cv::Mat src;
src = stuff;
cv::Mat dst;
//then call it
bitwise_not(src,dst);
If the function you want to do element by element is non-existent in the library or isn't an overloaded operator you can always do it the brute force way...
for(...) {
for (...) {
dst.at<int>(i,j) = ! src.at<int>(i,j);
}
}

Convert cv::MAT image to CVD::Image

I wanted to convert a cv::MAT image to a CVD::Image but i don't know how can I do. The reason is because previously I had a CVD::Image and I transformed it to cv::MAT in order to set a ROI region in the image, and now, I need the picture in CVD.
The code used to perform it, it's the following:
CVD::Image<CVD::byte> Imatge_a_modificar;
Imatge_a_modificar.copy_from(mimFrameBW_workingCopy); //The image is copied from another one
int x = frameWidth/2;
int y = frameHeight/2;
CvRect sROI = cvRect(x,y, frameWidth/2, frameHeight/2);
int xroi = sROI.x;
int yroi = sROI.y;
cv::Mat image(frameWidth,frameHeight,CV_8UC4,Imatge_a_modificar.data());
cv::Mat imageROI(image, sROI);
First of all, use cv::Rect, not CvRect. The latter is the obsolete C type from OpenCV version 1.
Concerning your question, you need to create CVD::Image the same way you created cv::Mat - from a given bitmap buffer, where your actual pixel values are stored. To access bitmap buffer of cv::Mat use ptr() method. To construct CVD::Image from a buffer, use the corresponding CVD::BasicImage constructor, and then convert CVD::BasicImage to CVD::Image using CVD::Image::copy_from method.

how can set a pointer to the content of a Mat variable in OpenCV

A Mat can be CV_8UC3, CV_8UC1, CV_32FC3 and etc. For example, for a Mat which is CV_8UC3, I can set a pointer: Vec3b *p to the Mat. However, If I only know the Mat's datatype which can be obtained using Mat.type(), How can I set a proper pointer?
The sad answer is: you can't. The type of data should be set in compilation time. But in your example actual type will be decided only during run time. You will have to put switch somewhere in your code. i.e. you will need to have different implementations of your algorithm for all possible types. Note however that you can prevent code duplication by using templates.
If you do know type of data, and the only thing you don't know is number of channels, then the problem is a bit simpler. For example if your image contains unsigned char you can write
uchar* p = img.ptr<uchar>();
And it doesn't matter whether your image have one channel or three. Of course when it comes to actually working with the pixels you do need this information.
Use a void pointer. Void pointers can point to any data type.
http://www.learncpp.com/cpp-tutorial/613-void-pointers/
If you know a type, you can set a pointer to the first element of the first row of cv::Mat using ptr (documentation)
cv::Mat matrix = cv::Mat::zeros(3, 3, CV_32F);
float* firstElement = matrix.ptr<float>(0);

Need to keep track of types of opencv Mats

So I'm using the class Mat from opencv in a program I'm writing. Mat looks something like this:
class Mat {
public:
Mat(int width, int height, int type);
template <typename T> T getElt(int x, int y);
int depth();
...
}
The type in the constructor specifies whether elements in the Mat are floats, ints, etc as well as the number of channels in the image. depth() returns the data type used to store image elements.
Unfortunately I have to call getElt() in my code. Whenever I do that I use a switch statement to check the depth of the Mat so I can call getElt() with the appropriate template parameter. Doing it that way is pretty verbose, so I was wondering if there was a better way to do it. Could I create a container for a Mat and use template magic create a method that returns a type as opposed to a value? Or could I use macros to make things more efficient and logical?
I'd rather not have to subclass Mat since there are several methods besides getElt() for which I have this same issue.
Edit: made the description more accurate.
You're probably looking for Mat_<T> instead. An black&white image really isn't the same as a greyscale image, and neither is equal to a color image. Those should be separate at compile time.
IIRC the 'type' in openCV MAT corresponds to the image type (ie number of channels) not the data type float/int/char etc.
If you want a templated image class that can transparently work with char/int/bool/double etc - take a look at CImg