No sound generated by SDL Audio Callback - c++

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

Related

SDL audio callback stops after two iterations

Given the following code:
#include <SDL2/SDL.h>
#include <SDL2/SDL_audio.h>
#include <iostream>
#include <chrono>
#include <thread>
static void SDLCallback(void *userData, Uint8 *data, int bytes) {
std::cerr << "SDLCallback: " << bytes / sizeof(float) << "\n";
}
int main() {
using namespace std::literals;
SDL_Init(SDL_INIT_AUDIO);
SDL_AudioDeviceID m_deviceId{};
SDL_AudioSpec m_desired, m_obtained;
m_desired.freq = 48000;
m_desired.format = AUDIO_F32SYS;
m_desired.channels = 2;
m_desired.samples = 1024;
m_desired.callback = SDLCallback;
m_desired.userdata = nullptr;
m_deviceId = SDL_OpenAudioDevice(nullptr, 0, &m_desired, &m_obtained, 0);
std::cerr << "SDL device: " << m_deviceId << std::endl;
if (m_deviceId < 2) {
std::cerr << "SDL: Couldn't open audio: " << SDL_GetError() << std::endl;
exit(1);
}
std::cerr << "rate: " << m_obtained.freq << "\n";
std::cerr << "samples: " << m_obtained.samples << "\n";
std::cerr << "bytes: " << m_obtained.size << "\n";
std::cerr << "channels: " << (int)m_obtained.channels << "\n";
SDL_PauseAudioDevice(m_deviceId, 0);
for (int i = 0; i < 10; i++) {
std::this_thread::sleep_for(100ms);
std::cerr << (SDL_GetAudioDeviceStatus(m_deviceId) == SDL_AUDIO_PLAYING)
<< std::endl;
}
SDL_CloseAudioDevice(m_deviceId);
SDL_Quit();
}
I am seeing the following output:
$ ./a.out
SDL device: 2
rate: 48000
samples: 1024
bytes: 8192
channels:
SDLCallback: 2048
SDLCallback: 2048
1
1
1
1
1
1
1
1
1
1
<program gets stuck on SDL_CloseAudioDevice>
That is, the SDLCallback function is called only twice at the beginning then not anymore, yet the audio is still marked as running. I am using PulseAudio.
What can I do to prevent that ? Where is my program wrong ? It works if I kill PulseAudio, but PulseAudio works fine for all my other software.
And if it is not wrong, how can I make sure that my users will never encounter that issue ? How can I recover without getting the program stuck on SDL_CloseAudioDevice ? As PulseAudio is very common among Linux users.

Reading .las version 1.3 using C++, and displaying the results using pcl library

I'm fairly new to the Point Cloud world. In addition, I'm not so experienced in C++.
I need to read .las files and process them using the pcl library. This is a sample file from the dataset that I need to read. I followed this youtube video. However, since the file I'm trying to read is of version 1.3, I followed the corresponding spec file to define the header fields and I used 'Data Record Format 3' which is the data record format mentioned in the file header.
This are my definitions for the header and data record format:
#pragma once
#include <string>
#include <vector>
struct float4
{
float x, y, z, intensity;
};
class PointCloud
{
public:
uint32_t getVertsCount();
float4* getVertsData();
template<typename PointT>
typename pcl::PointCloud<PointT>::Ptr read(const std::string& path);//void read(const std::string &path);
private:
std::vector<float4> verts;
#pragma pack(1)
struct Header
{
char magic[4];
uint16_t fileSourceID;
uint16_t globalEncoding;
uint32_t guidData1;
uint16_t guidData2;
uint16_t guidData3;
uint8_t guidData4[8];
uint8_t versionMaj, versionMin;
char systemIdentifier[32];
char genSoftware[32];
uint16_t creationDay, creationYear;
uint16_t headerSize;
uint32_t pointDataOffset;
uint32_t numVarLenRecords;
uint8_t pointDataRecordFormat;
uint16_t pointDataRecordLen;
uint32_t numberOfPoints;
uint32_t numPointsByReturn[5];
double scaleX, scaleY, scaleZ;
double offsetX, offsetY, offsetZ;
double maxX, minX, maxY, minY, maxZ, minZ;
uint64_t waveform;
};
//#pragma pack(1)
struct PointRecord3
{
uint32_t x, y, z;
uint16_t intensity;
uint8_t flags;
uint8_t classification;
uint8_t scanAngleRank;
uint8_t userData;
uint16_t pointSourceId;
double gpsTime;
uint16_t red;
uint16_t green;
uint16_t blue;
};
};
I used the following code to read the point data, but I failed to get correct points:
template<typename PointT>
typename pcl::PointCloud<PointT>::Ptr PointCloud::read(const string& path)
{
ifstream inf(path, ios::binary);
typename pcl::PointCloud<PointT>::Ptr lasCloud(new pcl::PointCloud<PointT>);
if (inf.is_open())
{
Header header;
inf.read((char*)&header, sizeof(header));
cout << "Signature: " << header.magic << endl;
cout << "Source ID: " << int(header.fileSourceID) << endl;
cout << "Global Encoding: " << int(header.globalEncoding) << endl;
cout << "Guid 1: " << int(header.guidData1) << endl;
cout << "Guid 2: " << int(header.guidData2) << endl;
cout << "Guid 3: " << int(header.guidData3) << endl;
cout << "Guid 4: " << header.guidData4 << endl;
cout << (int)header.versionMaj << '.' << (int)header.versionMin << endl;
cout << "Sys Identifier: " << header.systemIdentifier << endl;
cout << "Gen Software: " << header.genSoftware << endl;
cout << "Creation Day: " << header.creationDay << endl;
cout << "Creation Year: " << header.creationYear << endl;
cout << header.headerSize << " == " << sizeof(header) << endl;
cout << "Point Data Offset: " << header.pointDataOffset << endl;
cout << "Number of Variable Len Records: " << header.numVarLenRecords << endl;
cout << "point Data Record Format: " << header.pointDataRecordFormat << endl;
cout << "point Data Record Len: " << header.pointDataRecordLen << endl;
cout << "Number of Points: " << header.numberOfPoints << endl;
cout << "Number of Points by Return: " << header.numPointsByReturn << endl;
cout << "Scales: " << header.scaleX << ", " << header.scaleY << ", " << header.scaleZ << endl;
cout << "Offsets: " << header.offsetX << ", " << header.offsetY << ", " << header.offsetZ << endl;
cout << "Xmin = " << header.minX << ", Ymin = " << header.minY << ", Zmin = " << header.minZ << endl;
cout << "Xmax = " << header.maxX << ", Ymax = " << header.maxY << ", Zmax = " << header.maxZ << endl;
cout << "Waveform: "<<header.waveform << endl;
assert(header.versionMaj == 1 && header.versionMin == 3);
//assert(header.headerSize == sizeof(header));
assert(header.pointDataRecordFormat == 3);
//inf.seekg(header.pointDataOffset);
inf.seekg(sizeof(header));
//inf.seekg(header.pointDataOffset+sizeof(header.waveform));
for (uint32_t i = 0; i < header.numberOfPoints; i++)
{
//PointRecord1* points = new PointRecord1[header.numberOfPoints];
PointRecord3 point;
//inf.read((char*)(points + i), sizeof(PointRecord1));
//inf.read((char*)&point, sizeof(PointRecord1));
inf.read((char*)&point, sizeof(PointRecord3));
PointT cloudPoint;
cloudPoint.x = (float)(point.x * header.scaleX) + header.offsetX;
cloudPoint.y = (float)(point.y * header.scaleY) + header.offsetY;
cloudPoint.z = (float)(point.z * header.scaleZ) + header.offsetZ;
cloudPoint.intensity = (float)(point.intensity) / 65536.0;
lasCloud->points.push_back(cloudPoint);
}
if (!inf.good())
throw runtime_error("Reading went wrong!");
}
else
{
throw runtime_error("Can't find any!");
}
lasCloud->width = lasCloud->points.size();
lasCloud->height = 1;
lasCloud->is_dense = true;
std::cout << "Cloud size = " << lasCloud->points.size() << endl;
return lasCloud;
}
int main (int argc, char** argv)
{
std::cout << "starting enviroment" << std::endl;
pcl::visualization::PCLVisualizer::Ptr viewer (new pcl::visualization::PCLVisualizer ("3D Viewer"));
CameraAngle setAngle = FPS; //XY, FPS, Side, TopDown
initCamera(setAngle, viewer);
pcl::PointCloud<pcl::PointXYZI>::Ptr inputCloudI; //
PointCloud pcd;
inputCloudI=pcd.read<pcl::PointXYZI>("C:/Users/hedey/OneDrive/Documents/Research_papers/STDF/10_4231_MFQF-Q141/I-65/LiDAR/RoadSurface/NB/20180524_I65_NB_RoadSurface_1_50.5.las");
std::cout << "Cloud size = " << inputCloudI->points.size() << endl;
renderPointCloud(viewer, inputCloudI, "lasCloud");
while (!viewer->wasStopped())
{
viewer->spinOnce();
}
}
There is a problem that I noticed. The header size is defined to be 227 (this is the value of the header size field). However, there is an 8-byte field named 'Start of Waveform Data Packet Record' at the end of the header, which if included in the header definition will make the header size 235 bytes. Also, the pointDataOffset field which was used to seek the points data in the youtube video is pointing to 227 bytes. When I used it to seek the points data, I got unreasonable point values.
My target is to process this point cloud and display it using the pcl cloud, but I'm failing to read the points correctly.
I have no idea about Lidar and *.las files, but I've noticed that the input file was created with libLAS
> file 20180524_I65_NB_RoadSurface_1_50.5.las
20180524_I65_NB_RoadSurface_1_50.5.las: LIDAR point data records, version 1.3, SYSID libLAS, Generating Software libLAS 1.6.0
So, why don't you use libLAS to read the data in? https://liblas.org/
libLAS comes with convenient CLI utility programs to handle las files, e.g.:
lasinfo 20180524_I65_NB_RoadSurface_1_50.5.las
---------------------------------------------------------
Header Summary
---------------------------------------------------------
Version: 1.3
Source ID: 0
Reserved: 0
Project ID/GUID: '00000000-0000-0000-0000-000000000000'
System ID: 'libLAS'
Generating Software: 'libLAS 1.6.0'
File Creation Day/Year: 144/2018
Header Byte Size 227
Data Offset: 227
Header Padding: 0
Number Var. Length Records: None
Point Data Format: 3
Number of Point Records: 22017565
Compressed: False
Number of Points by Return: 0 0 0 0 0
Scale Factor X Y Z: 0.00100000000000 0.00100000000000 0.00100000000000
Offset X Y Z: 590284.000 4339456.000 157.000
Min X Y Z: 589879.772 4338728.975 149.667
Max X Y Z: 590334.248 4339568.021 178.397
Spatial Reference: None
---------------------------------------------------------
Schema Summary
---------------------------------------------------------
Point Format ID: 3
Number of dimensions: 16
Custom schema?: false
Size in bytes: 34
Dimensions
---------------------------------------------------------
'X' -- size: 32 offset: 0
'Y' -- size: 32 offset: 4
'Z' -- size: 32 offset: 8
'Intensity' -- size: 16 offset: 12
'Return Number' -- size: 3 offset: 14
'Number of Returns' -- size: 3 offset: 14
'Scan Direction' -- size: 1 offset: 14
'Flightline Edge' -- size: 1 offset: 14
'Classification' -- size: 8 offset: 15
'Scan Angle Rank' -- size: 8 offset: 16
'User Data' -- size: 8 offset: 17
'Point Source ID' -- size: 16 offset: 18
'Time' -- size: 64 offset: 20
'Red' -- size: 16 offset: 28
'Green' -- size: 16 offset: 30
'Blue' -- size: 16 offset: 32
---------------------------------------------------------
Point Inspection Summary
---------------------------------------------------------
Header Point Count: 22017565
Actual Point Count: 22017565
Minimum and Maximum Attributes (min,max)
---------------------------------------------------------
Min X, Y, Z: 600191.027, 4313816.564, 148.621
Max X, Y, Z: 600212.594, 4314678.007, 156.632
Bounding Box: 600191.027, 4313816.564, 600212.594, 4314678.007
Time: 55449082.421688, 55488872.904376
Return Number: 0, 0
Return Count: 0, 0
Flightline Edge: 0, 0
Intensity: 0, 255
Scan Direction Flag: 0, 0
Scan Angle Rank: 0, 0
Classification: 1, 3
Point Source Id: 0, 31
User Data: 0, 0
Minimum Color (RGB): 0 0 0
Maximum Color (RGB): 0 0 0
Number of Points by Return
---------------------------------------------------------
(1) 22017565
Number of Returns by Pulse
---------------------------------------------------------
(0) 22017565
Point Classifications
---------------------------------------------------------
7187055 Unclassified (1)
8128678 Ground (2)
6701832 Low Vegetation (3)
-------------------------------------------------------
0 withheld
0 keypoint
0 synthetic
-------------------------------------------------------
and
las2txt 20180524_I65_NB_RoadSurface_1_50.5.las qq.txt && head qq.txt
600209.243,4313837.086,155.155
600209.342,4313839.620,155.191
600209.232,4313836.806,155.154
600209.338,4313839.516,155.197
600209.221,4313836.523,155.165
600209.333,4313839.398,155.194
600209.206,4313836.177,155.158
600209.328,4313839.285,155.200
600209.189,4313835.778,155.145
600209.322,4313839.152,155.193
This means that the file is OK, the library works, and you'll save yourself lots of time learning the basic library usage rather then trying to reimplement it yourself (think of various data formats etc., error handling etc., testing etc., getting feedback in case of troubles, etc., and your time)

Clicking in ALSA tone generator

I'm learning to use ALSA on a Raspberry Pi 2. I've written a small test program in C++ to generate a 440 Hz test tone. It makes the tone, but there is a clicking sound about twice per second in the tone.
Does anyone have an idea why this might be happening? The code is below.
#include <cmath>
#include <climits>
#include <iostream>
#include <alsa/asoundlib.h>
#include "definitions.hpp"
using namespace std;
int main() {
int ret;
snd_pcm_t* pcm_handle; // device handle
snd_pcm_stream_t stream = SND_PCM_STREAM_PLAYBACK;
snd_pcm_hw_params_t* hwparams; // hardware information
char* pcm_name = strdup("plughw:0,0"); // on-board audio jack
int rate = 48000;
const uint16 freq = 440;
long unsigned int bufferSize = 8192*4;
const uint32 len = bufferSize*100;
const float32 arg = 2 * 3.141592 * freq / rate;
sint16 vals[len];
for(int i = 0; i < len; i = i + 2) {
vals[i] = SHRT_MAX * cos(arg * i / 2);
}
snd_pcm_hw_params_alloca(&hwparams);
ret = snd_pcm_open(&pcm_handle, pcm_name, stream, 0);
cout << "Opening: " << snd_strerror(ret) << endl;
ret = snd_pcm_hw_params_any(pcm_handle, hwparams);
cout << "Initializing hwparams structure: " << snd_strerror(ret) << endl;
ret = snd_pcm_hw_params_set_access(pcm_handle, hwparams,
SND_PCM_ACCESS_RW_INTERLEAVED);
cout << "Setting access: " << snd_strerror(ret) << endl;
ret = snd_pcm_hw_params_set_format(pcm_handle, hwparams,
SND_PCM_FORMAT_S16_LE);
cout << "Setting format: " << snd_strerror(ret) << endl;
ret = snd_pcm_hw_params_set_rate(pcm_handle, hwparams,
rate, (int)0);
cout << "Setting rate: " << snd_strerror(ret) << endl;
ret = snd_pcm_hw_params_set_channels(pcm_handle, hwparams, 2);
cout << "Setting channels: " << snd_strerror(ret) << endl;
ret = snd_pcm_hw_params_set_periods(pcm_handle, hwparams, 2, 0);
cout << "Setting periods: " << snd_strerror(ret) << endl;
ret = snd_pcm_hw_params_set_buffer_size_near(pcm_handle, hwparams,
&bufferSize);
cout << "Setting buffer size: " << snd_strerror(ret) << endl;
ret = snd_pcm_hw_params(pcm_handle, hwparams);
cout << "Applying parameters: " << snd_strerror(ret) << endl;
cout << endl << endl;
const void* ptr = (const void*)&vals;
int err;
do {
ptr += bufferSize;
ret = snd_pcm_writei(pcm_handle,
ptr, len);
if(ret < 0) {
err = snd_pcm_prepare(pcm_handle);
cout << "Preparing: " << snd_strerror(err)
<< endl;
}
} while(ret < 0);
cout << "Writing data: " << ret << ", " << snd_strerror(ret)
<< endl;
}
When you run it, you get this terminal output. Of course, there's no write error, just the number of bits written.
pi#raspberrypi:~/radio $ ./bin/alsatest
Opening: Success
Initializing hwparams structure: Success
Setting access: Success
Setting format: Success
Setting rate: Success
Setting channels: Success
Setting periods: Success
Setting buffer size: Success
Applying parameters: Success
Writing data: 344110, Unknown error 344110
UPDATE - NEXT DAY
OK. I've hooked the output up to my handy-dandy oscilloscope and saw the following waveform. There seems to be a discontinuity in the signal every time there's a click. I added a few lines to count how many nearly-zero values were next to each other in my sinusoid array, and there were none. Oddly enough, the ALSA sample program /test/pcm.c makes a perfect wave. Perhaps I need to write in really small chunks? There doesn't seem to be much difference between my code and the example.

Head Pose Estimation on Random Forest in G Fanelli's paper

I have been working on head pose estimation on depth data. And I have read G Fanelli's paper-"Real Time Head Pose Estimation from Consumer Depth Cameras" "Real Time Head Pose Estimation with Random Regression Forests". I test the data and the code Fanelli published on the website(http://www.vision.ee.ethz.ch/~gfanelli/head_pose/head_forest.html). However when I run the code, there is a problem. The error information is "usage: ./head_pose_estimation config_file depth_image". I think it is about file reading but I don't how to fix it.
and the code is like this:
int main(int argc, char* argv[])
{
if( argc != 3 )
{
cout << "usage: ./head_pose_estimation config_file depth_image" << endl;
exit(-1);
}
loadConfig(argv[1]);
CRForestEstimator estimator;
if( !estimator.loadForest(g_treepath.c_str(), g_ntrees) ){
cerr << "could not read forest!" << endl;
exit(-1);
}
string depth_fname(argv[2]);
//read calibration file (should be in the same directory as the depth image!)
string cal_filename = depth_fname.substr(0,depth_fname.find_last_of("/")+1);
cal_filename += "depth.cal";
ifstream is(cal_filename.c_str());
if (!is){
cerr << "depth.cal file not found in the same folder as the depth image! " << endl;
return -1;
}
//read intrinsics only
float depth_intrinsic[9]; for(int i =0; i<9; ++i) is >> depth_intrinsic[i];
is.close();
Mat depthImg;
//read depth image (compressed!)
if (!loadDepthImageCompressed( depthImg, depth_fname.c_str() ))
return -1;
Mat img3D;
img3D.create( depthImg.rows, depthImg.cols, CV_32FC3 );
//get 3D from depth
for(int y = 0; y < img3D.rows; y++)
{
Vec3f* img3Di = img3D.ptr<Vec3f>(y);
const int16_t* depthImgi = depthImg.ptr<int16_t>(y);
for(int x = 0; x < img3D.cols; x++){
float d = (float)depthImgi[x];
if ( d < g_max_z && d > 0 ){
img3Di[x][0] = d * (float(x) - depth_intrinsic[2])/depth_intrinsic[0];
img3Di[x][1] = d * (float(y) - depth_intrinsic[5])/depth_intrinsic[4];
img3Di[x][2] = d;
}
else{
img3Di[x] = 0;
}
}
}
g_means.clear();
g_votes.clear();
g_clusters.clear();
string pose_filename(depth_fname.substr(0,depth_fname.find_last_of('_')));
pose_filename += "_pose.bin";
cv::Vec<float,POSE_SIZE> gt;
bool have_gt = false;
//try to read in the ground truth from a binary file
FILE* pFile = fopen(pose_filename.c_str(), "rb");
if(pFile){
have_gt = true;
have_gt &= ( fread( &gt[0], sizeof(float),POSE_SIZE, pFile) == POSE_SIZE );
fclose(pFile);
}
//do the actual estimate
estimator.estimate( img3D,
g_means,
g_clusters,
g_votes,
g_stride,
g_maxv,
g_prob_th,
g_larger_radius_ratio,
g_smaller_radius_ratio,
false,
g_th
);
cout << "Heads found : " << g_means.size() << endl;
//assuming there's only one head in the image!
if(g_means.size()>0){
cout << "Estimated: " << g_means[0][0] << " " << g_means[0][1] << " " << g_means[0][2] << " " << g_means[0][3] << " " << g_means[0][4] << " " << g_means[0][5] <<endl;
float pt2d_est[2];
float pt2d_gt[2];
if(have_gt){
cout << "Ground T.: " << gt[0] << " " << gt[1] << " " << gt[2] << " " << gt[3] << " " << gt[4] << " " << gt[5] <<endl;
cv::Vec<float,POSE_SIZE> err = (gt-g_means[0]);
//multiply(err,err,err);
for(int n=0;n<POSE_SIZE;++n)
err[n] = err[n]*err[n];
float h_err = sqrt(err[0]+err[1]+err[2]);
float a_err = sqrt(err[3]+err[4]+err[5]);
cout << "Head error : " << h_err << " mm " << endl;
cout << "Angle error : " << a_err <<" degrees " << endl;
pt2d_gt[0] = depth_intrinsic[0]*gt[0]/gt[2] + depth_intrinsic[2];
pt2d_gt[1] = depth_intrinsic[4]*gt[1]/gt[2] + depth_intrinsic[5];
}
pt2d_est[0] = depth_intrinsic[0]*g_means[0][0]/g_means[0][2] + depth_intrinsic[2];
pt2d_est[1] = depth_intrinsic[4]*g_means[0][1]/g_means[0][2] + depth_intrinsic[5];
}
return 0;
}
can anyone could tell me how to fix the problem?Thanks so much!
You should always read the readme.txt (here attached in head_pose_estimation.tgz) before testing an application:
To run the example code, type ./head_pose_estimation config.txt
data/frame_XXXX_depth.bin. The config.txt file contains all parameters
needed for the head pose estimation, e.g., the path to the forest, the
stride, and z threshold used to segment the person from the
background.

VTKPNGWriter printing out black images?

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