Hi I have the following piece of code:
void ViewPlane::colourPixel(const int u, const int v, const Colour c){
int step = img->widthStep;
cout << "U: " << u << ", V: " << v << ", step: " << step << "\n";
cout << "Colour: " << c.r << ", " << c.g << ", " << c.b << "\n";
cout << "Data: " << v*step+u*3 << ", " << v*step+u*3+1 << ", " << v*step+u*3+2 << "\n";
cout << "Data: " << data[v*step+u*3] << ", " << data[v*step+u*3+1] << ", " << data[v*step+u*3+2] << "\n";
//swap colours round as opencv default image is bgr, not rgb
data[v*step+u*3] = c.b;
cout << "done it\n";
data[v*step+u*3+1] = c.g;
cout << "done it\n";
data[v*step+u*3+2] = c.r;
cout <<"done it\n";
}
img is an IplImage pointer, and data is
data = (uchar *)img->imageData;
I am looping through lots of values of u and v (image coordinates) and assigning a colour to each pixel. However the code just stops half way through this pixel when it reaches u = 148.
Printing out the values reveals the green pixel at this point originally contains '*', and is the only one up to that point which does so. Here is a copy of the output:
....
U: 146, V: 0, step: -1219934912
Colour: 0, 0, 0
Data: 438, 439, 440
Data:
done it
done it
done it
U: 147, V: 0, step: -1219934912
Colour: 0, 0, 0
Data: 441, 442, 443
Data:
done it
done it
done it
U: 148, V: 0, step: -1219934912
Colour: 0, 0, 0
Data: 444, 445, 446
Data: �, *, �
done it
So my question is, what does this star mean? And why is it stopping me from assigning data there?
EDIT: The image size is 400x400px
PS: I just tried commenting out the green channel assignment and this error happens again for the red channel further on. This time it held '#' before assignment, so this makes me think it has no bearing on what's going wrong...In that case, what on earth? I'm not out of bounds of the array, the value I'm inserting is an integer 0...
Your program's output shows step being "-1219934912". It makes it look like you have a stray img pointer. It's rather strange that each line in image would take ~1GB
Related
I'm trying to write a program that reads and writes PCL files without PCD (Point Cloud library),
I can read the positions of each point without a problem,
but the RGB value is written in uint32_t and I do not know how to read this format and translate it to RGB values.
# .PCD v0.7 - Point Cloud Data file format
VERSION 0.7
FIELDS x y z rgb
SIZE 4 4 4 4
TYPE F F F F
COUNT 1 1 1 1
WIDTH 100
HEIGHT 1
VIEWPOINT 0 0 0 1 0 0 0
POINTS 100
DATA ascii
-0.031568773 -0.99000001 0.99000013 2.3418052e-038
0.031568673 -0.98999995 0.99000013 2.3418052e-038
-0.031568974 -0.54999995 0.77000004 2.3418052e-038
0.031568889 -0.54999995 0.77000004 2.3418052e-038
convert the last value (2.3418052e-038) to RGB value?
Is there a way to do this without Point Cloud library?
Thank you.
Please read the below PLY format data from Wikipedia,
https://en.wikipedia.org/wiki/PLY_(file_format)
Adding a sample snippet to write a PLY file,
std::string fname = "sample.ply";
std::ofstream out(fname);
out << "ply\n";
out << "format ascii 1.0\n";
out << "comment\n";
out << "element vertex " << cloud5->points.size() << "\n";
out << "property float" << sizeof(float) * 8 << " x\n";
out << "property float" << sizeof(float) * 8 << " y\n";
out << "property float" << sizeof(float) * 8 << " z\n";
out << "property uchar red\n";
out << "property uchar green\n";
out << "property uchar blue\n";
out << "property list uchar int vertex_indices\n";
out << "end_header\n";
out.close();
out.open(fname, std::ios_base::app);
for (size_t i = 0; i < cloud5->points.size(); ++i)
{
out << cloud5->points[i].x << " " << cloud5->points[i].y << " " << cloud5->points[i].z << " " << (int)cloud5->points[i].r
<< " " << (int)cloud5->points[i].g << " " << (int)cloud5->points[i].b << "\n";
}
out.close();
So something strange is happening in my code at the moment, it is about the following register __m256i local, assigned during a computation somewhere, as well as __m256i mask, which is unrelated to local.
Where running the following :
std::cout << _mm256_extract_epi32 (local, 0) << ", " << _mm256_extract_epi32(local,1) << ", " << _mm256_extract_epi32(local,2) << ", " << _mm256_extract_epi32(local,3) << ", " << _mm256_extract_epi32(local,4) << ", " << _mm256_extract_epi32(local,5) << ", " << _mm256_extract_epi32(local,6) << ", " << _mm256_extract_epi32(local,7) << std::endl;
for (int l = 0; l < 8; ++l)
{
if (mask[l]) mask[l] = 0; else mask[l] = 1;
}
std::cout << _mm256_extract_epi32 (local, 0) << ", " << _mm256_extract_epi32(local,1) << ", " << _mm256_extract_epi32(local,2) << ", " << _mm256_extract_epi32(local,3) << ", " << _mm256_extract_epi32(local,4) << ", " << _mm256_extract_epi32(local,5) << ", " << _mm256_extract_epi32(local,6) << ", " << _mm256_extract_epi32(local,7) << std::endl;`
I obtain 519, 519, 519, 519, 519, 519, 519, 519 for the first output and 0, 0, 0, 0, 0, 0, 0, 0 for the second, even though they come from the same register. Any idea how something like this could happen ?
Is the intent of your for-loop to access the 32-bit words within the 256-bit mask vector? That's not the correct way to do that. When you use the subscript operator to access mask, the compiler is overrunning the location of the actual mask variable in memory, and clobbering the subsequent 7x 256-byte region following it.
If you want to easily access the 32-bit words within mask, try declaring it as:
union vec8x32_t
{
__m256i vector;
uint32_t words[8];
};
vec8x32_t mask;
Then you can do like:
// Do some AVX thing with mask:
mask.vector = _mm256_set_epi32(0, 1, 0, 1, 0, 1, 0, 1);
// Manipulate the components of mask:
for (int l = 0; l < 8; ++l)
{
if (mask.words[l]) mask.words[l] = 0; else mask.words[l] = 1;
}
I want to convert a single set of YUV value to BGR. My code is as follows:
yuv = [100, 50, 150]
cv::Mat bgr_mat;
cv::Mat yuv_mat(1,1,CV_8UC3,cv::Scalar(yuv[0],yuv[1],yuv[2]));
cv::cvtColor(yuv_mat,bgr_mat,cv::COLOR_YUV2BGR);
cv::Vec3b bgr = bgr_mat.at<cv::Vec3b>(0,0);
cout << "b: " << (float)bgr.val[0] << " , g: " << (float)bgr.val[1] << " , r: " << (float)bgr.val[2] << endl;
The output I get is - b: 125, g: 118, r: 0
But the expected output is b: 0, g: 112, r: 128
Can somebody please tell me where am I going wrong?
If you are using Opencv 2.4 It is a known issue
Acording to responses on a similar question
There is a possible workarond:
yuv = [100, 50, 150]
cv::Mat bgr_mat;
cv::Mat yuv_mat(1,1,CV_8UC3,cv::Scalar(yuv[0],yuv[1],yuv[2]));
cv::cvtColor(yuv_mat,bgr_mat,cv::COLOR_YUV2BGR);
cv::cvtColor(bgr_mat,bgr_mat,cv::COLOR_BGR2RGB);
cv::Vec3b bgr = bgr_mat.at<cv::Vec3b>(0,0);
cout << "b: " << (float)bgr.val[0] << " , g: " << (float)bgr.val[1] << " , r: " << (float)bgr.val[2] << endl;
Output:
b: 0 , g: 118 , r: 125
cv::Mat x(2,2,CV_32F);
x.at<float>(0,0)=0.7;
x.at<float>(0,1) = 0.8;
x.at<float>(1,0) = 0.72;
x.at<float>(1,1) = 0.68;
x.convertTo( x, CV_8U, 255, 0 );
std::cout << x.at<int>(0,0) << std::endl;
std::cout << x.at<int>(0,1) << std::endl;
std::cout << x.at<float>(1,0) << std::endl; // I deliberately put <float> just to see what happens
std::cout << x.at<int>(1,1) << std::endl;
The output is:
-1380397902
1
1.54154e-40
0
I was expecting an output like:
178
204
184
173
What am I doing wrong?
if your Mat is CV_8U now, you will have to access it as
x.at<uchar>(1,1)
the next problem will be printing out the number correctly, cout, seeing a char , will try to print a letter, so you will have to cast it to int:
std::cout << int(x.at<uchar>(0,0)) << std::endl;
then, if your mat is 2x2, you can't access an element at 2,2, this is out of bounds, and will lead to UB. !
(in c++, we index from 0..n-1, right ?)
so, here, the corrected example:
cv::Mat x(2,2,CV_32F);
x.at<float>(0,0)=0.7;
x.at<float>(1,0) = 0.8;
x.at<float>(0,1) = 0.72;
x.at<float>(1,1) = 0.68;
Mat y;
x.convertTo( y, CV_8U, 255, 0 );
cout << int(y.at<uchar>(0,0)) << std::endl;
cout << int(y.at<uchar>(1,0)) << std::endl;
cout << int(y.at<uchar>(0,1)) << std::endl;
cout << int(y.at<uchar>(1,1)) << std::endl;
cerr << x << endl;
cerr << y << endl;
178
204
184
173
[0.69999999, 0.72000003;
0.80000001, 0.68000001]
[178, 184;
204, 173]
I am doing some image processing using ITK and then using VTK to print the results in a .png format however, the output image is always black.
Currently, I am converting itk::Image to vtk::vtkImageData using the itk::ImagetoVTKImageFilter(typedeffed to ITKtoVTKFilterType in my code).
ITKtoVTKFilterType::Pointer itk2vtkGray = ITKtoVTKFilterType::New();
itk2vtkGray->SetInput(grayBinary); //grayBinary is of type itk::Image<unsigned short, 2>
itk2vtkGray->Update();
vtkSmartPointer<vtkImageData> grayVTK = vtkSmartPointer<vtkImageData>::New();
grayVTK->SetExtent(extent);
grayVTK->SetSpacing(m_spacing);
grayVTK->SetScalarTypeToUnsignedShort();
grayVTK->SetNumberOfScalarComponents(1);
grayVTK->AllocateScalars();
grayVTK->DeepCopy(static_cast<vtkImageData*>(itk2vtkGray->GetOutput()));
//grayVTK = itk2vtkGray->GetOutput();
I have even confirmed that my VTK ImageData contains values of either 255 or 0 using the following code.
int *dims = grayVTK->GetDimensions();
std::cout << "Dims: " << " x: " << dims[0] << " y: " << dims[1] << " z: " << dims[2] << std::endl;
std::cout << "Number of points: " << grayVTK->GetNumberOfPoints() << std::endl;
std::cout << "Number of cells: " << grayVTK->GetNumberOfCells() << std::endl;
for (int y = 0; y < dims[1]; y++)
{
for (int x = 0; x < dims[0]; x++)
{
unsigned short *pixel = static_cast<unsigned short*>(grayVTK->GetScalarPointer(x,y,0));
std::cout << "PIXEL LOC/VAL "<< y*dims[0] + x << " " << pixel[0] <<std::endl;
}
std::cout << std::endl;
}
I then go on to do an ImageCast to ensure the type of the data is unsignedShort.
vtkSmartPointer<vtkImageCast> cast2 = vtkSmartPointer<vtkImageCast>::New();
cast2->SetInput(grayVTK);
cast2->SetOutputScalarTypeToUnsignedShort();
cast2->ClampOverflowOn();
cast2->Update();
Then finally I use vtkPNGwriter to output the .png files. Notice that I have tried to output both the actual vtkImageData as well as output from the ImageCastFilter.
vtkSmartPointer<vtkPNGWriter> writer =
vtkSmartPointer<vtkPNGWriter>::New();
writer->SetFileName(filename.toStdString().c_str());
writer->SetInputConnection(cast2->GetOutputPort());
//writer->SetInput(grayVTK); I have tried to method as well but to no success
writer->Write();
However, the .png output is always black. Does anyone know what I am doing wrong.
For future reference it seems that many PNG readers do not display 16 bit data. Hence the casting I was doing to unsigned short at the end should have rather been to char.
vtkSmartPointer<vtkImageCast> cast2 = vtkSmartPointer<vtkImageCast>::New();
cast2->SetInput(grayVTK);
cast2->SetOutputScalarTypeToChar();
cast2->ClampOverflowOn();
cast2->Update();