I want to make a bicublic 2D spline Interpolation. For that I opted for using the library Alglib. I have two vectors xs and ys and a matrix magnitudes. According to the docs I wrote this (magnitude is a double[N,27]):
for (int i = 0; i < 27; i++)
{
ys[i] = i;
}
for (int i = 0; i < N; i++)
{
xs[i] = i;
}
alglib.spline2dbuildbicubic(xs, ys,magnitudes,N, 27, out f);
I get the exception "alglib+alglibexception: Exception of type 'alglib+alglibexception' was thrown."
You have to write:
alglib.spline2dbuildbicubic( ys,xs,magnitudes,N, 27, out f);
Take a look here.
Related
I would like to fill a matrix column wise. I have the following numpy code which I am having difficulty converting to C++ Armadillo.
# numpy code
m = np.zeros((nrows, nrows))
# fill a matrix of lags
for i in range(0, nrows):
r = np.roll(vec_v, i)
m[:, i] = r
where vec_v is a single column vector and nrows is the number of rows in that column vector.
This is my Armadillo attempt
# armadillo conversion
mat m(nrows, nrows); m.zeroes();
for(int i = 0; i < nrows; i++){
vec r = shift(vec_v, i)
m.col(i).fill(r);
}
What is the reccommended way to initialize a matrix then fill the values column-wise.
The = operator should work here.
mat m(nrows, nrows); m.zeros();
for(int i = 0; i < nrows; i++){
vec r = shift(vec_v, i);
m.col(i) = r;
}
Matrix initialization can be simplified and the generation of the temporary r vector can be avoided, as below.
mat m(nrows, nrows, fill::zeros);
for(int i = 0; i < nrows; i++){
m.col(i) = shift(vec_v, i);
}
How to efficiency linearized Mat (symmetric matrix) to one row by right triangle.
For example, when I have:
0aabbb
b0aaaa
ba0bba
bac0aa
aaaa0c
abcab0
and then from that I get:
aabbbaaaabbaaac
Something like this:
...
template<class T>
Mat SSMJ::triangleLinearized(Mat mat){
int c = mat.cols;
Mat row = Mat(1, ((c*c)-c)/2, mat.type());
int i = 0;
for(int y = 1; y < mat.rows; y++)
for(int x = y; x < mat.cols; x++) {
row.at<T>(i)=mat.at<T>(y, x);
i++;
}
return row;
}
...
Since data in your mat is just a 1d array stored in row.data you can do whatever you want with it. I don't think you will find anything more special (w/o using vectorized methods) than just copying from this array.
int rows = 6;
char data[] = { 0,1,2,3,4,5,
0,1,2,3,4,5,
0,1,2,3,4,5,
0,1,2,3,4,5,
0,1,2,3,4,5};
char result[100];
int offset = 0;
for (int i = 0; i < 5; offset += 5-i, i++) {
memcpy(&result[offset] , &data[rows * i + i + 1], 5 - i);
}
Or with opencv Mat it would be
int rows = mat.cols;
char result[100]; // you can calculate how much data u need
int offset = 0;
for (int i = 0; i < 5; offset += 5-i, i++) {
memcpy(&result[offset] , &mat.data[rows * i + i + 1], 5 - i);
}
Mat resultMat(1, offset, result);
I want to do in OpenCV something like "A(A == val) = 0" that works in Matlab. I implemented some code but these are too slow (I use it many times)
I tried to do something like:
MatIterator_<T> it;
for (int i = 0; i < rows; i++){
tmp = in.row(i);
end = tmp.end<T>();
for (it = tmp.begin<T>(); it != end; ++it)
if (*it == val) *it = 0;
}
And
for (int i = 0; i < rows; i++){
*ptr = in.ptr<T>(i);
for (int j = 0; j < cols; j++){
if (*ptr == val) *ptr = 0;
ptr++;
}
}
I hope some suggestions. Thanks in advance.
This sets all elements of target that are 42 to the new value, 12:
cv::Mat mask = target == 42;
target.setTo(12, mask);
How can I convert byte array to Mat which is received from socket ?.
My client application will send color image data like this
Mat frame; //colour image
int imgSize = frame.total()*frame.elemSize();
int bytes = send(clientSock, frame.data, imgSize, 0));//write to the socket
And the server will receives the data like
char sockData[imgSize];
Mat img;
for (int i = 0; i < imgSize; i += bytes) {
bytes = recv(connectSock, sockData +i, imgSize - i, 0));
}
// Write to mat
for (int i = 0; i < img.rows; i++) {
for (int j = 0; j < img.cols; j++) {
(img.row(i)).col(j) = (uchar)sockData[((img.cols)*i)+j];
}
}
I am getting distorted image at the receiver. Is there any problem in my code ?
Thanks in advance.......
If you have colour image you may read it in a math with 3 channels of uchar so change this piece of code:
for (int i = 0; i < img.rows; i++) {
for (int j = 0; j < img.cols; j++) {
(img.row(i)).col(j) = (uchar)sockData[((img.cols)*i)+j];
}
}
with this:
int baseIndex = 0;
for (int i = 0; i < img.rows; i++) {
for (int j = 0; j < img.cols; j++) {
img.at<cv::Vec3b>(i,j) = cv::Vec3b(sockData[baseIndex + 0],
sockData[baseIndex + 1],
sockData[baseIndex + 2]);
baseIndex = baseIndex + 3;
}
}
Maybe this should work.
Doesn't this work?
cv::Mat frame(img.rows, img.cols, CV_8UC3, sockData);
Just replace CV_8UC3 with the correct image format:
CV_<bit-depth>{U|S|F}C(<number_of_channels>)
see https://docs.opencv.org/2.4/modules/core/doc/basic_structures.html
Edit: There is a 5th additional field which can be useful. The number of bytes per row (in case there are a few padding bytes). In working with V4L2 today, I successfully used this cv::Mat constructor:
v4l2_format camera_format = ...; // see https://linuxtv.org/downloads/v4l-dvb-apis/uapi/v4l/vidioc-g-fmt.html#description
cv::Mat mat(camera_format.fmt.pix.height,
camera_format.fmt.pix.width,
CV_8UC3,
raw_data_ptr,
camera_format.fmt.pix.bytesperline);
I solved the problem using below code.
int ptr=0;
for (int i = 0; i < img.rows; i++) {
for (int j = 0; j < img.cols; j++) {
img.at<cv::Vec3b>(i,j) = cv::Vec3b(sockData[ptr+0],sockData[ptr+1],sockData[ptr+2]);
ptr=ptr+3;
}
}
Adding to Michele answer, one can also use the MatIterator to solve this.
cv::Mat m;
m.create(10, 10, CV_32FC3);
// This is the socket data.
float *array = (float *)malloc( 3*sizeof(float)*10*10 );
cv::MatIterator_<cv::Vec3f> it = m.begin<cv::Vec3f>();
for (unsigned i = 0; it != m.end<cv::Vec3f>(); it++ ) {
for ( unsigned j = 0; j < 3; j++ ) {
(*it)[j] = *(array + i );
i++;
}
}
Now you have a float cv::Mat. In case of 8 bit, simply change float to uchar and Vec3f to Vec3b and CV_32FC3 to CV_8UC3
I currently want to read in some values into a 3-channel, 480 row by 640 column matrix of 8 bit unsigned integer values. I am initializing the matrix like this:
Declaration:
rgbMatrix = Mat::zeros(480,640,CV_8UC3);
When I try to iterate through the entire matrix I am unable to assign/grab values using the following method. The values simply stay 0. My code looks like this:
for (int i = 0; i < rgbMatrix.rows; i++)
{
for (int j = 0; j < rgbMatrix.cols; j++)
{
(rgbMatrix.data + rgbMatrix.step * i)[j * rgbMatrix.channels() + 0] = *value0*;
(rgbMatrix.data + rgbMatrix.step * i)[j * rgbMatrix.channels() + 1] = *value1*;
(rgbMatrix.data + rgbMatrix.step * i)[j * rgbMatrix.channels() + 2] = *value2*;
}
}
However, when I declare three separate 1-channel matrices (also 480 row by 640 column of 8 bit unsigned integer values) and attempt to access elements of those matrices the following code works:
Declaration:
rgbMatrix0 = Mat::zeros(480,640,CV_8UC1);
rgbMatrix1 = Mat::zeros(480,640,CV_8UC1);
rgbMatrix2 = Mat::zeros(480,640,CV_8UC1);
for (int i = 0; i < rgbMatrix0.rows; i++)
{
for (int j = 0; j < rgbMatrix0.cols; j++)
{
(rgbMatrix0.data + rgbMatrix0.step * i)[j] = *value0*;
(rgbMatrix1.data + rgbMatrix1.step * i)[j] = *value1*;
(rgbMatrix2.data + rgbMatrix2.step * i)[j] = *value2*;
}
}
Now, I want to use just one matrix for these operations, as having to keep track of three separate variables will get tiresome after a while. I have a feeling that I am not accessing the right point in memory for the three-channel matrix. Does anyone know how I can accomplish what I did in the second portion of code but using one three-channel matrix instead of three separate one-channel matrices?
Thanks.
There are plenty of ways to do it, for example:
cv::Mat rgbMatrix(480,640,CV_8UC3);
for (int i = 0; i < rgbMatrix.rows; i++)
for (int j = 0; j < rgbMatrix.cols; j++)
for (int k = 0; k < 3; k++)
rgbMatrix.at<cv::Vec3b>(i,j)[k] = value;
[k] here is the channel value.
To set the all the matrix elements to a specific value like 5 for example you can do this:
cv::Mat rgbMatrix2(cv::Size(480,640), CV_8UC3, cv::Scalar(5,5,5));
std::cout << rgbMatrix2 << std::endl;
Sorry I can't see your code since I am writing from iPhone. When you use 3 channel matrix you can get the pixel using:
Vec3b pix = rgbMatrix.at(row,col);
Now you can access channel using:
pix[0] = 255; pix[1] += pix[2];
P.s. Generally rgbMatrix pixel is of type vec3b or vec3d. Always cast image.at<> with relevant type
Very Simple using Vec3b - for uchar, Vec3i - for int, Vec3f - for float, Vec3d - for double
Mat rgbMatrix = Mat::zeros(480,640,CV_8UC1);
for (int i = 0; i < rgbMatrix.rows; i++)
{
for (int j = 0; j < rgbMatrix.cols; j++)
{
rgbMatrix.at<Vec3b>(i,j)[0] = *value0;
rgbMatrix.at<Vec3b>(i,j)[1] = *value1;
rgbMatrix.at<Vec3b>(i,j)[2] = *value2;
}
}
vector<cv::Point3f> xyzBuffer;
cv::Mat xyzBuffMat = cv::Mat(307200, 1, CV_32FC3);
for (int i = 0; i < xyzBuffer.size(); i++) {
xyzBuffMat.at<cv::Vec3f>(i, 1, 0) = xyzBuffer[i].x;
xyzBuffMat.at<cv::Vec3f>(i, 1, 1) = xyzBuffer[i].y;
xyzBuffMat.at<cv::Vec3f>(i, 1, 2) = xyzBuffer[i].z;
}
Here, 0, 1, and 2 are respectively the channels that store x, y and z values.