I am using CImg for Image processing assignment. After calling transpose() with the following code
cout << image_subsample.width() << ","<<image_subsample.height() << "transpose:" << image_subsample.transpose().width() <<"," <<image_subsample.transpose().height() << endl;
The output is
1200,1transpose:1200,1200
the expected output of transpose is
1200,1transpose:1,1200
Am I missing something?
You actually transpose your matrix twice in your example, so the output you get is logical.
Either use get_transpose() or better store your transposed matrix somewhere before displaying its size.
CImg<> transp = img.get_transpose();
fprintf(stderr,"%d,%d",transp.width(),transp.height());
Related
I have a publish-subscribe type of a node that receives pose information (position and orientation) from the subscribed data stream and it should compute the inverse and publish out.
In order to do so I'm creating a 4-by-4 homogeneous transformation matrix from the original pose data.
Inverse it using the Eigen C++ template library, convert the transformation matrix back to position and orientation form and publish it.
When I plotted the published data stream I noticed some noise so I ended up publishing the original data too for comparison, here is what I did:
convert original_pose to TF matrix, named as original_TF
convert original_TF back to pose, named as original_pose_
publish original_pose_
inverse original_TF assign to inverted_TF
convert inverted_TF to pose, named as inverted_pose_
publish inverted_pose_
When I plot the X, Y, Z position fields, I'm seeing a significant amount of noise (spikes and notches in the visual below) in the inverted pose data. Since I'm using the same functions to convert the original pose to TF and back, I know that those equations aren't the source of the noise.
Blue is the original, whereas red is the inverted.
Here is the code. Really nothing extraordinary.
bool inverse_matrix(std::vector<std::vector<double> > & input, std::vector<std::vector<double> > & output)
{
// TODO: Currently only supports 4-by-4 matrices, I can make this configurable.
// see https://eigen.tuxfamily.org/dox/group__TutorialMatrixClass.html
Eigen::Matrix4d input_matrix;
Eigen::Matrix4d output_matrix;
Eigen::VectorXcd input_eivals;
Eigen::VectorXcd output_eivals;
input_matrix << input[0][0], input[0][1], input[0][2], input[0][3],
input[1][0], input[1][1], input[1][2], input[1][3],
input[2][0], input[2][1], input[2][2], input[2][3],
input[3][0], input[3][1], input[3][2], input[3][3];
cout << "Here is the matrix input:\n" << input_matrix << endl;
input_eivals = input_matrix.eigenvalues();
cout << "The eigenvalues of the input_eivals are:" << endl << input_eivals << endl;
if(input_matrix.determinant() == 0) { return false; }
output_matrix = input_matrix.inverse();
cout << "Here is the matrix output:\n" << output_matrix << endl;
output_eivals = output_matrix.eigenvalues();
cout << "The eigenvalues of the output_eivals are:" << endl << output_eivals << endl;
// Copy output_matrix to output
for (int i = 0; i < 16; ++i)
{
int in = i/4;
int im = i%4;
output[in][im] = output_matrix(in, im);
}
return true;
}
-- Edit 1 --
I printed out the eigenvalues of the input and output matrices of the inverse_matrix function.
Here is the matrix input:
0.99916 -0.00155684 -0.0409514 0.505506
0.00342358 -0.992614 0.121267 0.19625
-0.0408377 -0.121305 -0.991775 1.64257
0 0 0 1
The eigenvalues of the input_eivals are:
(1,0)
(-0.992614,0.121312)
(-0.992614,-0.121312)
(1,0)
Here is the matrix output:
0.99916 0.00342358 -0.0408377 -0.438674
-0.00155684 -0.992614 -0.121305 0.39484
-0.0409514 0.121267 -0.991775 1.62597
-0 -0 0 1
The eigenvalues of the output_eivals are:
(1,0)
(-0.992614,0.121312)
(-0.992614,-0.121312)
(1,0)
-- Edit 2 --
I don't quite understand what you are plotting. Is it original_pose.{X,Y,Z} and inverted_pose.{X,Y,Z}? Then the "spikes" will really depend on the orientation-part of the matrix.
I am plotting original_pose_{position.x, position.y, position.z} and inverted_pose_{position.x, position.y, position.z} where the complete data that's published is <variable_name>{position.x, position.y, position.z, orientation.w, orientation.x, orientation.y, orientation.z}.
Can you elaborate on "the "spikes" will really depend on the orientation-part of the matrix."?
Also, how is your description related to the code-snippet? (I don't see any matching variable names).
I've identified that the source of the noise is the inversion, which is the item number 4 in my description: inverse original_TF assign to inverted_TF. To relate one another, I'm calling the function as follows:
isSuccess = inverse_matrix(original_TF, inverted_TF);
How do you store "poses" (is that the vector<vector> in your snippet)?
Yes, I'm storing them in 2-dimensional vectors of type double.
At any point, do you use Eigen::Transform to store transformations, or just plain Eigen::Matrix4d?
No, I'm only using Eigen::Matrix4d locally in the inverse_matrix function to be able to make use of the Eigen library for computation.
I took an image and I wanted to write the image as its corresponding pixel values and I have done the code and it compiled but the problem is that, I stored those values in a txt file and I copied those values to an excel sheet and what I see is that the pixel values that I got are only for half of the picture i.e when I see it as a whole picture the pixels show me the half the picture or less I dont know, but it isnt showing me the complete picture.
Help me.
#include <opencv2/opencv.hpp>
using namespace cv;
#include <fstream>
using namespace std;
int main()
{
Mat colorImage = imread("/home/bmit/display_image/CIRCLE.jpg");
// Open the file in write mode.
ofstream outputFile("name.txt");
// Iterate through pixels.
int r, c;
for (r = 1; colorImage.rows > r ;r++)
{
for (c = 1; colorImage.cols > c ; c++)
{
int pixel = colorImage.at<uchar>(r,c);
outputFile << pixel << '\t';
}
outputFile << endl;
}
// Close the file.
outputFile.close();
return 0;
}
There are a number of errors which I think are adding up to create this issue. The first is that for a colour image, there isn't really a single "pixel value" - there is a red component, a green component, a blue component (and possibly an alpha channel as well). I'm going to assume from this point onwards that you actually want the BGR values for each pixel sequentially.
cv::Mat is generally a wrapper around a pointer to a large singular block of continuous memory (it isn't always continuous but usually is). The Mat.at<typename>() method is one of the ways of accessing this data, using the typename to interpret it and cast the data accessed.
The issue you are having is the total information stored in this matrix is more than row*cols of uchars. The matrix is storing row*cols*3 trios of blue,green, and red uchars. The line of code int pixel = colorImage.at<uchar>(r,c); is accessing some point in this data sequence based on the size of a uchar, the number of rows in the image, and the values of r & c.
For instance, at some point in the innerloop you will call int pixel = colorImage.at<uchar>(r,c); when r is equal to the number of rows and c equal to the number of columns. You want this value of pixel to be the "pixel value" of the lower right pixel, but what you are actually getting is the value of one of the channel values for a pixel about a 3rd of the width along and a 3rd of the height down the image.
To fix this you have a number of options. I think you'll find reading some of the tutorials on the OpenCV website (this one probably being the most relevant) useful. But if you replace the loop in your code with the following it should work, although I haven't tested it.
for (r=0;r<colorImage.rows; r++)
{
for (r=0; c<colorImage.cols; c++)
{
Point3_<uchar> pixel = colorImage.at<Point3_<uchar>>(r,c);
outputFile << pixel.x << '\t'<< pixel.y << '\t'<< pixel.z << '\t';
}
outputFile << endl;
}
Note that this will be in order BGR, if you require RGB just swap the order of pixel.x & pixel.z
This is a part of my code and it's result in opengl/c++(using visual studio 2013):
GLint *raspos = new GLint[];
glRasterPos2i(56, 56);
glGetIntegerv(GL_CURRENT_RASTER_POSITION, raspos);
cout << " , X : " << raspos[0] << " and " << " Y : " << raspos[1];
result
X : 125 and Y : 125
i can't understand what's going on! why glRasterPos2i changes the arguments ?
The coordinates passed to glRasterPos are subject to the transformation pipeline. The values you retrieve is the raster position in window coordinates after undergoing those transformations.
Because the raster position is transform by the current projection and modelview matrices just like an ordinary vertex is, but querying GL_CURRENT_RASTER_POSITION is retrieving the window space coordinates.
I try to transpose from one MatrixX* into another (not quadratic but with correct dimensions). However the best I could find is the Transpose< Derived > ::transpose() function.
Is there even a call which puts the result into an already allocated Matrix instead of allocating a new one?
EDIT:
Actually I was using Eigen::Map on top of the Matrix.
typedef Eigen::Matrix<std::uint8_t, Eigen::Dynamic, Eigen::Dynamic> matrix_type;
typedef Eigen::Map<matrix_type> map_type;
const map_type src ( src_ptr , width , height );
map_type dest( dest_ptr, height, width );
map.transposeInPlace();
Using transposeInPlace() triggers an assert in Derived& DenseBase<Derived>
::lazyAssign(const DenseBase<OtherDerived>& other).
Try to use transposeInPlace() function
Here is the documentation: http://eigen.tuxfamily.org/dox/TutorialMatrixArithmetic.html
For in-place transposition, as for instance in a = a.transpose(),
simply use the transposeInPlace() function:
MatrixXf a(2,3); a << 1, 2, 3, 4, 5, 6;
cout << "Here is the initial matrix a:\n" << a << endl;
a.transposeInPlace();
cout << "and after being transposed:\n" << a << endl;
UPDATE: As Zeta mentioned in comment, matrix object should be resizable - this is always true for all MatrixX* objects.
Using Eigen::Map on top of a Matrix indeed results in an assert, since it seems like transposeInPlace is not possible yet for Eigen::Map (AKA a bug).
Luckily for me, using regular ::transpose was fine, since Eigen uses late assigning of data.
I'm trying to use OpenCV to find the RGB values of a pixel in an image. so far I've tried the following:
int blue = ((uchar *)(img->imageData + y*img->widthStep))[x*img->nChannels + 0];
int green = ((uchar *)(img->imageData + y*img->widthStep))[x*img->nChannels + 1];
int red = ((uchar *)(img->imageData + y*img->widthStep))[x*img->nChannels + 2];
int blue = ((float *)(img->imageData + i*img->widthStep))[j*img->nChannels + 0];
int green = ((float *)(img->imageData + i*img->widthStep))[j*img->nChannels + 1];
int red = ((float *)(img->imageData + i*img->widthStep))[j*img->nChannels + 2];
CvPoint pt = {5,5};
uchar* temp_ptr = &((uchar*)(img->imageData + img->widthStep*pt.y))[pt.x*3];
int blue = temp_ptr[0];
int green = temp_ptr[1];
int red = temp_ptr[2];
But in all of the above, I get the same error:
Unhandled exception at 0x00f5104f in test.exe: 0xC0000005: Access violation reading location: 0x00000048
The last hex number (0x0...48) never changes. I looks like this can be caused by writing further than the bounds of an array. So I've run each of the examples in isolation without any other code at all, and still get the same error. What is causing this error and how can I fix it?
Extra info: Windows 7, MSVC 2010 Express, OpenCV 2.1
--UPDATE--
I've realised the above code is more compicated than it needs to be, so I took the snippet provided by karlphillip (thanks!) as a base and used a similar method. I'm still getting an error, and this time in an even stranger place:
IplImage *slice = cvLoadImage("test.png");
int bpp = slice ->nChannels;
The error occurs on the second line, and is still an Access Violation. There is no code executed before this to do with OpenCV, just some variable initializations. 'test.png' is just a 7*7 pixel 'X' I made in paint to test this out, using a .jpg has hte saem result.
To make sure I hadn't installed OpenCV improperly, I used this code (copied from below) in isolation:
int main ()
{
IplImage* pRGBImg = cvCreateImage(cvSize(5,5),IPL_DEPTH_8U,3);
int width = pRGBImg->width;
int height = pRGBImg->height;
int bpp = pRGBImg->nChannels;
cvNamedWindow("Image view", 1);
cvShowImage("Image view", pRGBImg);
cvWaitKey(0);
cvDestroyWindow("Image view");
for (int i=0; i < width*height*bpp; i+=bpp)
{
if (!(i % (width*bpp))) // print empty line for better readability
std::cout << std::endl;
std::cout << std::dec << "R:" << (int) pRGBImg->imageData[i] <<
" G:" << (int) pRGBImg->imageData[i+1] <<
" B:" << (int) pRGBImg->imageData[i+2] << " ";
}
}
This didn't return any errors, but I did get some possibly strange results, here are the first few lines of console output:
R:13 G:-16 B:-83
R:-70: G:13 B:-16
R:-83 G:-70 B: 13
Negative RGB values? Is this to be expected, or is even this not working. If it is normal, then the image I'm loading ('test.png') must be the problem. But, what am I doing wrong if a simple request for the number of channels causes an access violation?
Without knowing the size of the image and how you are looping through it to read its pixels, its impossible to tell what you are doing wrong. Most probably you are trying to read beyond the image boundaries (therefore, access violation).
Anyway, you could add debugs to your code and pinpoint the exact line that triggers this error.
This is how I usually do to iterate through the pixels of an image:
IplImage* pRGBImg = cvLoadImage(input_file.c_str(), CV_LOAD_IMAGE_UNCHANGED);
int width = pRGBImg->width;
int height = pRGBImg->height;
int bpp = pRGBImg->nChannels;
for (int i=0; i < width*height*bpp; i+=bpp)
{
if (!(i % (width*bpp))) // print empty line for better readability
std::cout << std::endl;
std::cout << std::dec << "R:" << (int) pRGBImg->imageData[i] <<
" G:" << (int) pRGBImg->imageData[i+1] <<
" B:" << (int) pRGBImg->imageData[i+2] << " ";
}
The problem probably caused by
IplImage *slice = cvLoadImage("test.png");
if the function failed, variable slice will be NULL, and any further dereferencing will leads to access violation.
Since opencv's dll may be installed on different path than your running application, it is advisable to provide "absolute file path" when calling opencv's function.
Try copy your sample image to c:\, and change your code into IplImage *slice = cvLoadImage("c:\\test.png");, I'd bet it will work like magic :)
Edit:
For your odd pixel values, it might caused by uninitialized memory contents
Try simplyfing the expression a little.
Get a pointer the image data, then calculate a pointer to the start of that row, then a pointer to the pixel, then the R,G,B values
As Martin says, precalculate things like your base addresses and offsets so you can more easily see what is going on. This is very important with pointer arithmetic (e.g. if img->ImgData is not a pointer to a byte-sized data type, your pointer arithmetic will be entirely wrong. Indeed, you appear to be indexing the same array (img->imageData) as both a pointer to uchar and a pointer to float...what is it?)
Also, check the inputs - Are you using a 24bpp or 32bpp test image? Is 'img' non-null? Are x,y coming in within the pixel-width and pixel-height ranges? Is widthStep sane, and expressed in terms of bytes? Stick lots of debugging ASSERTs in your code and you'll eliminate the possibility of a lot of simple errors occurring.
I have created a super safe, automatic garbage collection, very fast, IplImage wrapper using boost::shared_ptr.
The image structure is called blImage and is available at:
http://www.barbato.us/2010/10/14/image-data-structure-based-shared_ptr-iplimage/
There you can download my blImageAPI and start having fun with opencv instead of sweating about pixel access.
Good luck and have fun creating image algorithms