I tried to use bitwise_or on two CV_8UC1 images, but the result is not what I expected.
In my case, for image_1, every pixel value is set to 2, and for image_2, every pixel value is set to 3, the output of bitwise_or is an image with every pixel value set to 5, while what I expected is every pixel value is 2|3, which should be 2.
Can someone tell me why?
The result of the bitwise or operation between 2 and 3 is 3. You can check it like this:
cout<<(2|3); // The result will be 3
Also, if you do a bitwise_or on two matrices that have all pixels 2 and 3 respectively, you should get a matrix with all its pixels set to 3, like in this example:
Mat m1 = Mat(3, 3, CV_8UC1, Scalar(2));
Mat m2 = Mat(3, 3, CV_8UC1, Scalar(3));
Mat r;
bitwise_or(m1, m2, r);
cout<<r;
Result:
[3, 3, 3;
3, 3, 3;
3, 3, 3]
Do you want to add the two images? If this is the case, you can simply use the + operator, like this:
Mat m1 = Mat(3, 3, CV_8UC1, Scalar(2));
Mat m2 = Mat(3, 3, CV_8UC1, Scalar(3));
Mat r = m1+m2;
cout<<r;
Result:
[5, 5, 5;
5, 5, 5;
5, 5, 5]
In decimal system, the equivalent of the or operation is the maximum operation. (Also, the equivalent of the and operation is the minimum operation).
If this is what you want, OpenCV provides a cv::max() function that calculates the elementwise maximum from two matrices of the same size. Here is an example:
Mat a = Mat::ones(3, 3, CV_8UC1) * 2;
Mat b = Mat::ones(3, 3, CV_8UC1) * 100;
cout<<a<<endl<<b<<endl;
Mat max = cv::max(a, b);
cout<<max;
The result is:
a=[2, 2, 2;
2, 2, 2;
2, 2, 2]
b=[100, 100, 100;
100, 100, 100;
100, 100, 100]
max=[100, 100, 100;
100, 100, 100;
100, 100, 100]
Related
I know that to implement the following
I would use this code:
Mat o_k;
Mat Lapl;
double lambda;
Laplacian(o_k, Lapl, o_k.depth(), 1, 1, 0, BORDER_REFLECT);
Lapl = 1.0 - 2.0*lambda*Lapl;
However, I am trying to implement in OpenCV the following equation:
I know the div, or divergence, term would be like this, right?
int ksize = parser.get<int>("ksize");
int scale = parser.get<int>("scale");
int delta = parser.get<int>("delta");
Sobel(res, sobelx, CV_64F, 1, 0, ksize, scale, delta, BORDER_DEFAULT);
Sobel(res, sobely, CV_64F, 0, 1, ksize, scale, delta, BORDER_DEFAULT);
div = sobelx + sobely;
Where res is the result of the term in parenthesis. But how I get the term in parenthesis?
Or am I doing this wrong? Would div above actually be equal to the gradient of res? If so, then how do I get the divergence?
EDIT:
According to this link, the magnitude can also be computed as mag = abs(x) + abs(y): https://docs.opencv.org/2.4/doc/tutorials/imgproc/imgtrans/sobel_derivatives/sobel_derivatives.html#sobel-derivatives
And since the div of a gradient is the Laplacian, would the below code be equivalent to the 2nd equation?
Sobel(res, sobelx, CV_64F, 1, 0, ksize, scale, delta, BORDER_DEFAULT);
Sobel(res, sobely, CV_64F, 0, 1, ksize, scale, delta, BORDER_DEFAULT);
convertScaleAbs( sobelx, abs_grad_x );
convertScaleAbs( sobely, abs_grad_y );
/// Total Gradient (approximate)
Mat mag;
addWeighted( abs_grad_x, 1, abs_grad_y, 1, 0, mag);
Laplacian(o_k, Lapl, o_k.depth(), 1, 1, 0, BORDER_REFLECT);
Mat top;
top = lambda * Lapl;
Mat result;
divide(top, mag, result);
I have three matrices, each of size 4x1. I want to copy all of these matrices to another matrix of size 4x3 and call it R. Is there a smart way to do it?
You can just use hconcat for horizontal concatenation. You can use it per matrix, e.g. hconcat( mat1, mat2, R ), or apply it directly on a vector or array of matrices.
Here's a sample code:
vector<Mat> matrices = {
Mat(4, 1, CV_8UC1, Scalar(1)),
Mat(4, 1, CV_8UC1, Scalar(2)),
Mat(4, 1, CV_8UC1, Scalar(3)),
};
Mat R;
hconcat( matrices, R );
cout << R << endl;
Here's the result:
[1, 2, 3;
1, 2, 3;
1, 2, 3;
1, 2, 3]
Program ended with exit code: 1
Similarly, if you want to do it vertically (stack by rows), use vconcat.
You can use
Mat R(3, 4, CV_32F); // [3 rows x 4 cols] with float values
mat1.copyTo(R.row(0));
mat2.copyTo(R.row(1));
mat3.copyTo(R.row(2));
or
Mat R(4, 3, CV_32F); // [4 rows x 3 cols] with float values
mat1.copyTo(R.col(0));
mat2.copyTo(R.col(1));
mat3.copyTo(R.col(2));
Alternatively, as #sub_o suggested, you can also use hconcat()/vconcat() to concatenate matrices.
For those using OpenCv in Python, if you have arrays A, B, and C, and want array D that is horizontal concatenation of the others:
D = cv2.hconcat((A, B, C))
There is also a vconcat method.
For example, I have a 2by3 matrix [1,0,5;1,0,-5], and a Mat trans_mat( 2, 3, CV_32FC1).
How can I assign those values to the trans_mat matrix?
Mat trans_mat( 2, 3, CV_32FC1);
trans_mat = (Mat_<float>(2, 3) << 1, 0, 5, 1, 0, -5);
I have been trying to achieve something which should pretty trivial and is trivial in Matlab.
Using methods of OpenCV, I want to simply achieve something such as:
cv::Mat sample = [4 5 6; 4 2 5; 1 4 2];
sample = 5*sample;
After which sample should just be:
[20 25 30; 20 10 25; 5 20 10]
I have tried scaleAdd, Mul, Multiply and neither allow a scalar multiplier and require a matrix of the same "size and type". In this scenario I could create a Matrix of Ones and then use the scale parameter but that seems so very extraneous
Any direct simple method would be great!
OpenCV does in fact support multiplication by a scalar value with overloaded operator*. You might need to initialize the matrix correctly, though.
float data[] = {1 ,2, 3,
4, 5, 6,
7, 8, 9};
cv::Mat m(3, 3, CV_32FC1, data);
m = 3*m; // This works just fine
If you are mainly interested in mathematical operations, cv::Matx is a little easier to work with:
cv::Matx33f mx(1,2,3,
4,5,6,
7,8,9);
mx *= 4; // This works too
For java there is no operator overloading, but the Mat object provides the functionality with a convertTo method.
Mat dst= new Mat(src.rows(),src.cols(),src.type());
src.convertTo(dst,-1,scale,offset);
Doc on this method is here
For big Mats you should use forEach.
If C++11 is available:
m.forEach<double>([&](double& element, const int position[]) -> void
{
element *= 5;
}
);
something like this.
Mat m = (Mat_<float>(3, 3)<<
1, 2, 3,
4, 5, 6,
7, 8, 9)*5;
Mat A = //data;//source Matrix
Mat B;//destination Matrix
Scalar alpha = new Scalar(5)//factor
Core.multiply(A,alpha,b);
I'm currently trying to rectify stereo cameras to create a disparity map. Unfortunately, I'm having trouble getting past the stereo rectification step because I keep receiving the error
"OpenCV Error: Bad argument in unknown function, file ..\..\..\modules\core\src\matrix.cpp, line 697."
The process is complicated by the fact that I'm not the one one who calibrated the cameras, nor do I have access to the cameras used to record the videos. I was given all of the calibration parameters (intrinsics, distortion coefficients, rotation matrix, and translation vector). As you can see, I've tried to turn these directly into CvMats and use them that way, but I get an error when I try to actually use them.
Thanks in advance.
CvMat li, lm, ri, rm, r, t, Rl, Rr, Pl, Pr;
double init_li[3][3] =
{ {477.984984743, 0, 316.17458671},
{0, 476.861945645, 253.45073026},
{0, 0 ,1} };
double init_lm[5] = {-0.117798518453, 0.147554949385, -0.0549082041898, 0, 0};
double init_ri[3][3] =
{{478.640315323, 0, 299.957994781},
{0, 477.898896505, 251.665771947},
{0, 0, 1}};
double init_rm[5] = {-0.10884732532, 0.12118405303, -0.0322073237741, 0, 0};
double init_r[3][3] =
{{0.999973709051976, 0.00129700728791757, -0.00713435189275776},
{-0.00132096594266573, 0.999993501087837, -0.00335452397041856},
{0.00712995468519435, 0.00336386001267643, 0.99996892361313}};
double init_t[3] = {-0.0830973040641153, -0.00062704210860633, 1.4287643345188e-005};
cvInitMatHeader(&li, 3, 3, CV_64FC1, init_li);
cvInitMatHeader(&lm, 5, 1, CV_64FC1, init_lm);
cvInitMatHeader(&ri, 3, 3, CV_64FC1, init_ri);
cvInitMatHeader(&rm, 5, 1, CV_64FC1, init_rm);
cvInitMatHeader(&r, 3, 3, CV_64FC1, init_r);
cvInitMatHeader(&t, 3, 1, CV_64FC1, init_t);
cvInitMatHeader(&Rl, 3,3, CV_64FC1);
cvInitMatHeader(&Rr, 3,3, CV_64FC1);
cvInitMatHeader(&Pl, 3,4, CV_64FC1);
cvInitMatHeader(&Pr, 3,4, CV_64FC1);
//frame is a cv::MAT holding the first frame of the video.
CvSize imageSize = frame.size();
imageSize.width /= 2;
//IT BREAKS HERE
cvStereoRectify(&li, &ri, &lm, &rm, imageSize, &r, &t, &Rl, &Rr, &Pl, &Pr);
so, you've been bitten by the c-api ? why don't you just turn your back on it ?
use the c++ api whenever possible, don't start learning opencv with the old(1.0), deprecated api, please !
double init_li[9] =
{ 477.984984743, 0, 316.17458671,
0, 476.861945645, 253.45073026,
0, 0 ,1 };
double init_lm[5] = {-0.117798518453, 0.147554949385, -0.0549082041898, 0, 0};
double init_ri[9] =
{ 478.640315323, 0, 299.957994781,
0, 477.898896505, 251.665771947,
0, 0, 1};
double init_rm[5] = {-0.10884732532, 0.12118405303, -0.0322073237741, 0, 0};
double init_r[9] =
{ 0.999973709051976, 0.00129700728791757, -0.00713435189275776,
-0.00132096594266573, 0.999993501087837, -0.00335452397041856,
0.00712995468519435, 0.00336386001267643, 0.99996892361313};
double init_t[3] = {-0.0830973040641153, -0.00062704210860633, 1.4287643345188e-005};
cv::Mat li(3, 3, CV_64FC1, init_li);
cv::Mat lm(5, 1, CV_64FC1, init_lm);
cv::Mat ri(3, 3, CV_64FC1, init_ri);
cv::Mat rm(5, 1, CV_64FC1, init_rm);
cv::Mat r, t, Rl, Rr, Pl, Pr; // note: no initialization needed.
//frame is a cv::MAT holding the first frame of the video.
cv::Size imageSize = frame.size();
imageSize.width /= 2;
//IT won't break HERE
cv::stereoRectify(li, ri, lm, rm, imageSize, r, t, Rl, Rr, Pl, Pr);
// no need ever to release or care about anything
Ok, so I figured out the answer. The problem was that I had only initialized headers for Rl, Rr, Pl, and Pr, but no memory was allocated for the data itself. I was able to fix it as follows:
double init_Rl[3][3];
double init_Rr[3][3];
double init_Pl[3][4];
double init_Pr[3][4];
cvInitMatHeader(&Rl, 3,3, CV_64FC1, init_Rl);
cvInitMatHeader(&Rr, 3,3, CV_64FC1, init_Rr);
cvInitMatHeader(&Pl, 3,4, CV_64FC1, init_Pl);
cvInitMatHeader(&Pr, 3,4, CV_64FC1, init_Pr);
Although, I have a theory that I might have been able to use cv::stereoRectify with cv::Mats as parameters, which would have made life much easier. I don't know if cv::stereoRectify exists, but it seems that versions of many of the other c functions are in the cv namespace. In case it's hard to tell, I'm very new to OpenCV.