VTKPNGWriter printing out black images? - c++

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();

Related

No sound generated by SDL Audio Callback

I am trying to get a simple sinewave sound generation example working using SDL 2.0.12 on Windows 10, but no sound is being output.
I have no idea if it is a problem with the code or with the output device or the audio drivers.
I'd really appreciate suggestions of how I can debug the problem further.
#include <iostream>
#include "SDL.h"
float sine_freq = 200.0f;
float audio_volume = 4000.0f;
float audio_frequency;
void SineAudioCallback(void* userdata, Uint8* stream, int len) {
float* buf = (float*)stream;
for (int i = 0; i < len / 4; ++i) {
buf[i] = (float)(audio_volume * sin(2 * M_PI * i * audio_frequency));
}
return;
}
int main(int argc, char* argv[])
{
if (SDL_Init(SDL_INIT_AUDIO)) {
return 1;
}
std::cout << "[SDL] Audio driver: " << SDL_GetCurrentAudioDriver() << std::endl;
SDL_AudioSpec want, have;
SDL_zero(want);
want.freq = 5000;
want.format = AUDIO_F32;
want.channels = 2;
want.samples = 4096;
want.callback = SineAudioCallback;
std::cout <<"[SDL] Desired - frequency: " << want.freq
<< ", format: f " << SDL_AUDIO_ISFLOAT(want.format) << " s " << SDL_AUDIO_ISSIGNED(want.format) << " be " << SDL_AUDIO_ISBIGENDIAN(want.format) << " sz " << SDL_AUDIO_BITSIZE(want.format)
<< ", channels: " << (int)want.channels << ", samples: " << want.samples << std::endl;
SDL_AudioDeviceID dev = SDL_OpenAudioDevice(NULL, 0, &want, &have, SDL_AUDIO_ALLOW_ANY_CHANGE);
if (!dev) {
SDL_Quit();
return 1;
}
std::cout << "[SDL] Desired - frequency: " << have.freq
<< ", format: f " << SDL_AUDIO_ISFLOAT(have.format) << " s " << SDL_AUDIO_ISSIGNED(have.format) << " be " << SDL_AUDIO_ISBIGENDIAN(have.format) << " sz " << SDL_AUDIO_BITSIZE(have.format)
<< ", channels: " << (int)have.channels << ", samples: " << have.samples << std::endl;
audio_frequency = sine_freq / have.freq;
SDL_PauseAudioDevice(dev, 0);
SDL_Delay(10000);
SDL_CloseAudioDevice(dev);
SDL_Quit();
return 0;
}
The output I get is
[SDL] Audio driver: wasapi
[SDL] Desired - frequency: 5000, format: f 256 s 32768 be 0 sz 32, channels: 2, samples: 4096
[SDL] Desired - frequency: 5000, format: f 256 s 32768 be 0 sz 32, channels: 2, samples: 118
So there is a difference between SDL_AudioSpec I want and have, in the number of samples being reduced.
I also get an error message relating to the dlls although I'm not sure if it is important.
avcore\audiocore\client\audioclient\audioclientcore.cpp(1839)\AUDIOSES.DLL!00007FFC48E00F8E: (caller: 0000000070D6BE39) ReturnHr(1) tid(46dc) 80070057 The parameter is incorrect.
It turns out there were two things I needed to do to solve this problem.
For a float type the sound wave can only take values from -1 to 1, whilst I was using a much greater volume boost. I needed to change
float audio_volume = 1.0f;
For Windows, the direct sound and winmm drivers give better sample lengths than wasapi. For SDL2 on Windows, you need SDL_AUDIODRIVER=directsound or SDL_AUDIODRIVER=winmm set as an environment variable. More details here

weird glm::mat2x4 assignment behaviour

I am trying to load freetype chars, stuff them into a texture as subimages and then render them instanced.
While most of it seems to work, right now I have a problem with storing the texture coordinates into a glm::mat2x4 matrix.
As can be seen below each character has a struct with information I right now deem necessary, including a matrix called face, which should store the texture coordinates.
But when it comes to assigning the coordinates, after leaving the loop in which it takes place, suddenly all the values go crazy, without any (wanted/ intended) operation taking place from my side.
After creating the texture atlas with freetype and putting all my structs into the map, I assign the width and height of my texture aw & ah to a storage class called c_atlas.
I calculate the texture coordinates in the loop shown below, make the glm::mat2x4 a 0.0f matrix and then stuff them into it. Couting them into the console gives the values I want.
After leaving the for loop I start another one, browsing over the matrix and cout them into the console, which gives me more or less random values in the range of e^-23 to e^32.
All of this happens in namespace foo and is called in a constructor of a class in the same namespace (sth. like this:)
foo::class::constructor()
{
call_function();
}
int main()
{
foo::class c;
c.call_function();
}
I crafted a minimum working example, but unfortunatly I am not able to replicate the error.
So I have the following loop running (a part of call_function():
namespace foo
{
namespace alphabet
{
const char path_arial[] = "res/font/consola.ttf";
class character
{
public:
glm::vec2 advance;
glm::vec2 bearing;
glm::vec2 size;
glm::vec2 offset;
glm::mat2x4 face;
};
std::map<char, character> char_map;
FT_Library m_ftlib;
FT_Face m_ftface;
GLuint m_VBO, m_VAO;
}
c_atlas ascii;
}
void foo::call_function()
{
//creating all the charactur structs with freetype and store them in the char_map
std::ofstream f("atlas_data.csv", std::ios::openmode::_S_app);
f << "letter;topleft.x;topleft.y;topright.x;topright.y;bottomright.x;bottomright.y;bottomleft.x;bottomleft.y" << std::endl;
for(auto c : alphabet::char_map)
{
std::cout << "b4: " << c.second.offset.x;
c.second.offset /= glm::vec2(aw,ah);
std::cout << "\nafter: " << c.second.offset.x << std::endl;
glm::vec2 ts = c.second.size/glm::vec2(aw,ah);
//couts the right values
uint16_t n = 0;
c.second.face = glm::mat2x4(0.0f);
for(uint16_t i = 0; i < 4; ++i)
{
std::cout << c.first << " at init:\n";
std::cout << c.second.face[0][i] << "\n";
std::cout << c.second.face[1][i] << std::endl;
}
//couts the right values
c.second.face[0][n++] = c.second.offset.x;
c.second.face[0][n++] = c.second.offset.y;
c.second.face[0][n++] = c.second.offset.x+ts.x;
c.second.face[0][n++] = c.second.offset.y;
n = 0;
c.second.face[1][n++]= c.second.offset.x+ts.x;
c.second.face[1][n++] = c.second.offset.y+ts.y;
c.second.face[1][n++] = c.second.offset.x;
c.second.face[1][n++]= c.second.offset.y+ts.y;
for(uint16_t i = 0; i < 4; ++i)
{
std::cout << c.first << " assigned:\n";
std::cout << c.second.face[0][i] << "\n";
std::cout << c.second.face[1][i] << std::endl;
}
//still couts the right values
f << (char)c.first << ";" << c.second.face[0].x << ";" << c.second.face[0].y << ";" << c.second.face[0].z << ";" << c.second.face[0].w << ";" << c.second.face[1].x << ";" << c.second.face[1].y << ";" << c.second.face[1].z << ";" << c.second.face[1].w << std::endl;
//the file also have the right values
}
f.close();
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
//yet here all the values totally off track, i.e. e^32 or e^-23 (while they should all be between 0.01f - 1.0f)
for(auto i : alphabet::char_map)
{
std::cout << "\ntopleft:\n";
std::cout << "X: " << i.second.face[0].x << " | " << "Y: " << i.second.face[0].x;
std::cout << "\ntopright:\n";
std::cout << "X: " << i.second.face[0].z << " | " << "Y: " << i.second.face[0].w;
std::cout << "\nbotleft:\n";
std::cout << "X: " << i.second.face[1].x << " | " << "Y: " << i.second.face[1].x;
std::cout << "\nbotright:\n";
std::cout << "X: " << i.second.face[1].z << " | " << "Y: " << i.second.face[1].w;
}
}
my mwe:
#include <iostream>
#include <string>
#include "glm/glm.hpp"
#include "GL/gl.h"
#include <map>
struct bin
{
glm::mat2x4 mat;
};
int main( int argc, char *argv[] )
{
std::map<char, bin> bucket;
uint16_t r = 0;
for(uint16_t n = 0; n < 7; ++n)
{
glm::vec4 v = glm::vec4(0.12128f, 0.12412f, 0.15532f, 0.23453f);
bin b;
r = 0;
b.mat[0][r++] = v.x;
b.mat[0][r++] = v.y;
b.mat[0][r++] = v.z;
b.mat[0][r++] = v.w;
r = 0;
b.mat[1][r++] = v.x;
b.mat[1][r++] = v.y;
b.mat[1][r++] = v.z;
b.mat[1][r++] = v.w;
bucket[n] = b;
}
for(auto it : bucket)
{
r = 0;
std::cout << "0:\t" << it.second.mat[0][0] << "\t" << it.second.mat[0][1] << "\t" << it.second.mat[0][2] << "\t" << it.second.mat[0][3] << "\n";
r = 0;
std::cout << "1:\t" << it.second.mat[1][0] << "\t" << it.second.mat[1][1] << "\t" << it.second.mat[1][2] << "\t" << it.second.mat[1][3] << std::endl;
}
return 0;
}
Right now I am totally lost, especially as my mwe works fine.
I am clueless what goes wrong after leaving the for-loop, so thanks for any thought on that!
Indeed, I could just rewrite that section and hope it would work - as my mwe does. But I would like to find out/ get help on finding out what exactly happens between the "assign" for loop and the "retrieve" for loop. Any ideas on that?
I made it work for me now:
Appartenly assigning the values this way:
for(auto c : alphabet::char_map)
{
c.second.face[0][n++] = c.second.offset.x;
//and so on
}
Did not work properly (for whatever reason..)
Changing this into a for(uint16_t i = 32; i < 128; ++i) worked for me. Also it was just the assigning loop, the auto-iterating ofer the map elsewhere works just fine.

How can I get rgb value from point cloud

I have a point-cloud. I want to get its RGB value. How can I do that?
To make my question clearer, please see the codes.
// Load the first input file into a PointCloud<T> with an appropriate type :
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud1 (new pcl::PointCloud<pcl::PointXYZRGB>);
if (pcl::io::loadPCDFile<pcl::PointXYZRGB> ("../data/station1.pcd", *cloud1) == -1)
{
std::cout << "Error reading PCD file !!!" << std::endl;
exit(-1);
}
I want to get each value alone
std::cout << " x = " << cloud1->points[11].x << std::endl;
std::cout << " y = " << cloud1->points[11].y << std::endl;
std::cout << " z = " << cloud1->points[11].z << std::endl;
std::cout << " r = " << cloud1->points[11].r << std::endl;
std::cout << " g = " << cloud1->points[11].g << std::endl;
std::cout << " b = " << cloud1->points[11].b << std::endl;
But as a result I get something like that :
x = 2.33672
y = 3.8102
z = 8.86153
r = �
g = w
b = �
From the point cloud docs:
A point structure representing Euclidean xyz coordinates, and the RGB color.
Due to historical reasons (PCL was first developed as a ROS package), the RGB information is packed into an integer and casted to a float. This is something we wish to remove in the near future, but in the meantime, the following code snippet should help you pack and unpack RGB colors in your PointXYZRGB structure:
// pack r/g/b into rgb
uint8_t r = 255, g = 0, b = 0; // Example: Red color
uint32_t rgb = ((uint32_t)r << 16 | (uint32_t)g << 8 | (uint32_t)b);
p.rgb = *reinterpret_cast<float*>(&rgb);
To unpack the data into separate values, use:
PointXYZRGB p;
// unpack rgb into r/g/b
uint32_t rgb = *reinterpret_cast<int*>(&p.rgb);
uint8_t r = (rgb >> 16) & 0x0000ff;
uint8_t g = (rgb >> 8) & 0x0000ff;
uint8_t b = (rgb) & 0x0000ff;
Alternatively, from 1.1.0 onwards, you can use p.r, p.g, and p.b directly.
Definition at line 559 of file point_types.hpp.

QT QImage, how to extract RGB?

I want to extract RGB from each pixel in QImage. Ideally, I want to use the img.bits() function.
QImage img;
if( img.load("Red.jpg") )
{
uchar *bits = img.bits();
for (int i = 0; i < 12; i++)
{
std::cout << (int) bits[i] << std::endl;
}
}
How to manipulate the returned bits? I expected all red because the picture is a pure red image created in Paint. However, I get 36, 27, 237, 255, 36 etc...
QImage img( "Red.jpg" );
if ( false == img.isNull() )
{
QVector<QRgb> v = img.colorTable(); // returns a list of colors contained in the image's color table.
for ( QVector<QRgb>::const_iterator it = v.begin(), itE = v.end(); it != itE; ++it )
{
QColor clrCurrent( *it );
std::cout << "Red: " << clrCurrent.red()
<< " Green: " << clrCurrent.green()
<< " Blue: " << clrCurrent.blue()
<< " Alpha: " << clrCurrent.alpha()
<< std::endl;
}
}
However this example above does returns the color table. Color table does not includes same colors twice. They will be added once in order of appearance.
If you want to get each pixels color, you can use next lines:
for ( int row = 1; row < img.height() + 1; ++row )
for ( int col = 1; col < img.width() + 1; ++col )
{
QColor clrCurrent( img.pixel( row, col ) );
std::cout << "Pixel at [" << row << "," << col << "] contains color ("
<< clrCurrent.red() << ", "
<< clrCurrent.green() << ", "
<< clrCurrent.blue() << ", "
<< clrCurrent.alpha() << ")."
<< std::endl;
}
Reference for bits() says:
Returns a pointer to the first pixel data. This is equivalent to scanLine(0).
So if you check reference for scanLine()
If you are accessing 32-bpp image data, cast the returned pointer to QRgb* (QRgb has a 32-bit size) and use it to read/write the pixel value. You cannot use the uchar* pointer directly, because the pixel format depends on the byte order on the underlying platform. Use qRed(), qGreen(), qBlue(), and qAlpha() to access the pixels.
One other option would probably be pixel() member function.
Hope that helps.
One of the problems with using the bits() function is that you need to know the format of the original image. You should convert it to RGB by using convertToFormat.
img = img.convertToFormat(QImage::Format_RGB888);
Now, when you call bits(), the data will be in the RGB format with the proper data alignment.
uchar *bits = img.bits();
for (int i = 0; i < (img.width() * img.height() * 3); i++)
{
std::cout << (int) bits[i] << std::endl;
}
In Qt 5.6 was introduced QColor QImage::pixelColor(int x, int y) method, so you can directly get color information from image pixel.

Getting pixel color with Magick++?

I've already asked this question, but that was about FreeImage. Now I'm trying to do the same thing with ImageMagick (to be more correct, with Magick++).
All I need is to get the RGB value of pixels in an image with the ability to print it out onto the screen. I asked this in the ImageMagick forum, but it seems there is nobody there. :-( Can anybody help, please?
Version 6 API
Given an "Image" object, you have to request a "pixel cache", then work with it. Documentation is here and here:
// load an image
Magick::Image image("test.jpg");
int w = image.columns();
int h = image.rows();
// get a "pixel cache" for the entire image
Magick::PixelPacket *pixels = image.getPixels(0, 0, w, h);
// now you can access single pixels like a vector
int row = 0;
int column = 0;
Magick::Color color = pixels[w * row + column];
// if you make changes, don't forget to save them to the underlying image
pixels[0] = Magick::Color(255, 0, 0);
image.syncPixels();
// ...and maybe write the image to file.
image.write("test_modified.jpg");
Version 7 API
Access to pixels has changed in version 7 (see: porting), but low-level access is still present:
MagickCore::Quantum *pixels = image.getPixels(0, 0, w, h);
int row = 0;
int column = 0;
unsigned offset = image.channels() * (w * row + column);
pixels[offset + 0] = 255; // red
pixels[offset + 1] = 0; // green
pixels[offset + 2] = 0; // blue
#Sga's answer didn't work for me, I'm using the ImageMagick-7.0.7-Q8 (8 bit depth) library.
Here's how I did it, to scan an image pixel by pixel and output each one's RGB value:
// "InitializeMagick" called beforehand!
void processImage()
{
std::ifstream fin;
std::stringstream fs;
fs << "/img.png";
std::cout << "Opening image \"" << fs.str() << "\".." << std::endl;
try
{
Image img;
img.read( fs.str() );
int imgWidth = img.columns();
int imgHeight = img.rows();
std::cout << "Image width: " << imgWidth << std::endl;
std::cout << "Image height: " << imgHeight << std::endl;
std::cout << "Image channels: " << img.channels() << std::endl;
img.modifyImage();
for ( int row = 0; row <= imgHeight; row++ )
{
for ( int column = 0; column <= imgWidth; column++ )
{
ColorRGB px = img.pixelColor( column, row );
std::cout << "Pixel " << column << "," << row << " R: " << px.red() << " G: " << px.green() <<
" B: " << px.blue() << std::endl;
}
}
}
catch ( Magick::Exception & error )
{
std::cerr << "Caught Magick++ exception: " << error.what() << std::endl;
}
fin.close(); // Close the file
}