AES128 encrypt/decrypt using gcrypt in c++ - libgcrypt

i couldnt find a working good example so ive created one
you can change mykey ,and make the iv random using one of the gcrypt function.
sample
#include <iostream>
#include <gcrypt.h>
typedef unsigned char byte;
using namespace std;
#define BLOCK 16
const byte mykey []= {0x2d,0x65,0x20,0x74,0x69,0x6D,0x65,0x20,0x66,0x6F,0x72};
const byte end1[] ={0x0};
const byte message [] = {0x4E,0x6F,0x77,0x20,0x69,0x73,0x20,0x74,0x68,0x65,0x20,0x74,0x69,0x6D,0x65,0x20,0x66,0x6F,0x72,0x20,0x61,0x6C,0x6C,0x20,0x67,0x6F,0x6F,0x64,0x20,0x6D,0x65,0x6E,0x20,0x74,0x6F,0x20,0x63,0x6F,0x6D,0x65,0x20,0x74,0x6F,0x20,0x74,0x68,0x65,0x20,0x61,0x69,0x64,0x65,0x20,0x6F,0x66,0x20,0x74,0x68,0x65,0x20,0x63,0x6F,0x75,0x6E,0x74,0x72,0x79,0x2E,0x00 };
const byte end[] = {0x00};
// encrypt
// Encrypt data in BLOCK in place if EDFLAG is zero; otherwise decrypt
// block in place.
#define roundup(x,n) \
n *((sizeof(x))/n + (((sizeof(x))%n)+1)/(((sizeof(x))%n)+1))
void verify ( gcry_error_t err, const char* msg ) {
if (err) {
cout << msg << " " << gcry_strsource(err)<< " / " << gcry_strerror(err) << endl;
exit(1);
}
}
/* PROGMA BEGIN
* encrypt decrypt
* using the GCRYPT */
int main (){
gcry_error_t err = 0;
// init the lib ..
if (!gcry_check_version (GCRYPT_VERSION))
{ cout << "gcrypt: library version mismatch" << endl; exit(1); }
err = gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
err |= gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0);
err |= gcry_control (GCRYCTL_RESUME_SECMEM_WARN);
err |= gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
verify (err,"gcrypt: failed initialization");
//init the operation mode
#define GCRY_CIPHER GCRY_CIPHER_AES128
#define GCRY_MODE GCRY_CIPHER_MODE_ECB
//#define GCRY_FLAG GCRY_CIPHER_ENABLE_SYNC
#define GCRY_FLAG 0
gcry_cipher_hd_t handle;
err = gcry_cipher_open( &handle, GCRY_CIPHER, GCRY_MODE, GCRY_FLAG);
verify ( err, "gcry_cipher_open" ) ;
byte iv[BLOCK];
memset(iv,0x23,BLOCK); // just for example, we should get it from the cipher word, first 16 bytes
memset(iv, 0x89 , BLOCK -4);
err = gcry_cipher_setiv(handle,iv,BLOCK);
verify( err, "set iv ");
cout <<"iv seT: "<< BLOCK << ":"<< iv << endl;
err = gcry_cipher_setkey(handle, mykey, sizeof(mykey));
verify( err, "set KeY ");
cout << "KeY set: "<< sizeof(mykey) <<":";// << mykey << endl;
for ( int i = 0 ; i <sizeof(mykey) ; ++i ) cout << mykey[i];
cout << endl;
// init done
// in = message
// out - new
unsigned char out[ roundup(message,BLOCK) ];
memset(out,0,roundup(message,BLOCK) );
//memcpy( out, message, sizeof(message));
size_t outsize = sizeof(out);
err = gcry_cipher_encrypt( handle, out, outsize, message, outsize);
verify( err, "encrypt " );
cout <<endl<< "encrypt in: " << sizeof(message) << ":" << message << endl ;
cout << "encrypt out: " << outsize << ":"<< out << endl<<endl;
unsigned char decrypt[roundup(out,BLOCK)]; // to out
memset(decrypt, 0 , roundup(out,BLOCK) );
size_t dsize= sizeof(decrypt);
err = gcry_cipher_decrypt( handle, decrypt, dsize, out, outsize);
verify( err, "decrypt " );
cout << "decrypt in: " << outsize << ":";
for ( int i = 0 ; i < outsize ; ++i ) cout << out[i];
cout << endl;
cout << "decrypt out: " << dsize << ":"<< decrypt << endl;
gcry_cipher_close(handle);
return 0;
}
/* g++ -std=c++11 xxx.cpp -L/usr/lib64 -lgcrypt -lgpg-error*/
any comment is welcome
i know it doesn't look that good , tried to be concised

Related

Matrix multiplication with vectorization in c++

I need to multiply and then add matrices AxB+C. Is there a way to do this operation in c++ such that vectorization is applied and the matrices are multiplied and added faster? If there is a reference or code for doing so it would be nice. Additionally do I need to modify something in order to enable vectorization.
Thank you in advance
EDIT:
//g++ -I/path/to/eigen -O3 -DEIGEN_NO_DEBUG -fopenmp new.cpp
// ./a.out
#pragma GCC optimize("O3","unroll-loops","omit-frame-pointer","inline") //Optimization flags
#pragma GCC option("arch=native","tune=native","no-zero-upper") //Enable AVX
#pragma GCC target("avx") //Enable AVX
#include <x86intrin.h> //AVX/SSE Extensions
#include <bits/stdc++.h> //All main STD libraries
#include <iostream>
#include <chrono>
#include <Eigen/Dense>
#include <unsupported/Eigen/FFT>
using namespace Eigen;
int main()
{
// Matrix2d mat;
// mat << 1, 2,
// 3, 4;
// mat= MatrixXd::Random(3000,3000);
// Vector2d u(-1,1), v(2,0);
// Matrix2d m1;
// auto start = std::chrono::steady_clock::now();
//
// m1 << mat*mat;
// auto end = std::chrono::steady_clock::now();
// std::cout << "Elapsed time in nanoseconds : "
// << std::chrono::duration_cast<std::chrono::nanoseconds>(end - start).count()
// << " ns" ;
// std::cout << "Here is mat*mat:\n" << mat*mat << std::endl;
// std::cout << "Here is mat*u:\n" << mat*u << std::endl;
// std::cout << "Here is u^T*mat:\n" << u.transpose()*mat << std::endl;
// std::cout << "Here is u^T*v:\n" << u.transpose()*v << std::endl;
// std::cout << "Here is u*v^T:\n" << u*v.transpose() << std::endl;
// std::cout << "Let's multiply mat by itself" << std::endl;
// mat = mat*mat;
// std::cout << "Now mat is mat:\n" << mat << std::endl;
// mat << 1, 2,
// 3, 4;
MatrixXf m1 = MatrixXf::Random(32,32);
MatrixXf m2 = MatrixXf::Random(32,32);
MatrixXf newM;
auto start = std::chrono::steady_clock::now();
newM=m1*m2;
auto end = std::chrono::steady_clock::now();
std::cout << "Elapsed time in nanoseconds : "
<< std::chrono::duration_cast<std::chrono::nanoseconds>(end - start).count()
<< " ns" ;
MatrixXf a = MatrixXf::Random(1, 32);
MatrixXf b = MatrixXf::Random(32, 32);
MatrixXf c = MatrixXf::Random(32, 1);
time_t start1 = clock();
start = std::chrono::steady_clock::now();
MatrixXf d = a * b * c;
end = std::chrono::steady_clock::now();
std::cout << "Elapsed time in nanoseconds : "
<< std::chrono::duration_cast<std::chrono::nanoseconds>(end - start).count()
<< " ns" ;
std::cout << (double)(clock() - start1) / CLOCKS_PER_SEC * 1000 << "ms" << std::endl;
const int ROWS = 32;
const int COLS = 32;
int random_matrix[ROWS][COLS];
int i;
int j;
/* initialize random seed: */
srand(static_cast<unsigned>(time(0)));
/* generate number: */
for (i=0;i<ROWS;i++)
{
for (j=0;j<COLS;j++)
random_matrix[i][j]= rand() % 100;
// std::cout << random_matrix[i][j] << std::endl; //display table
}
int mult[10][10], r1, c1, r2, c2, k;
r1=32*32;
c2=32*32;
c1=32*32;
start = std::chrono::steady_clock::now();
start1 = clock();
for(i = 0; i < r1; ++i)
for(j = 0; j < c2; ++j)
{
mult[i][j]=0;
}
for(i = 0; i < r1; ++i)
for(j = 0; j < c2; ++j)
for(k = 0; k < c1; ++k)
{
// std::cout << "Elapsed time in nanoseconds : "
// << std::chrono::duration_cast<std::chrono::nanoseconds>(end - start).count()
// << " ns" ;
mult[i][j] += random_matrix[i][k] * random_matrix[k][j]* random_matrix[k][j];
}
end = std::chrono::steady_clock::now();
double end1=clock() - start1;
std::cout << "Elapsed time in nanoseconds : "
<< std::chrono::duration_cast<std::chrono::nanoseconds>(end - start).count()
<< " ns" ;
std::cout << (double)(end1) / CLOCKS_PER_SEC * 1000 << "ms" << std::endl;
return 0;

How to track the 2d points over the images for 3d-reconstruction as specified in opencv sfm pipeline?

I am trying to do 3D reconstruction using this code from opencv. As far as I understood, I need a textfile with the 2D points as per the given format. I am wondering if anyone could help me in getting these 2D points they mention in this program. I have a set of images with the calibration parameters but I have been not able to understand how could I track and save these 2D points e.g. the first point in frame 1 is the same point in frame 2 in the format they specified .
#include <opencv2/core.hpp>
#include <opencv2/sfm.hpp>
#include <opencv2/viz.hpp>
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
using namespace cv;
using namespace cv::sfm;
static void help() {
cout
<< "\n------------------------------------------------------------\n"
<< " This program shows the camera trajectory reconstruction capabilities\n"
<< " in the OpenCV Structure From Motion (SFM) module.\n"
<< " \n"
<< " Usage:\n"
<< " example_sfm_trajectory_reconstruction <path_to_tracks_file> <f> <cx> <cy>\n"
<< " where: is the tracks file absolute path into your system. \n"
<< " \n"
<< " The file must have the following format: \n"
<< " row1 : x1 y1 x2 y2 ... x36 y36 for track 1\n"
<< " row2 : x1 y1 x2 y2 ... x36 y36 for track 2\n"
<< " etc\n"
<< " \n"
<< " i.e. a row gives the 2D measured position of a point as it is tracked\n"
<< " through frames 1 to 36. If there is no match found in a view then x\n"
<< " and y are -1.\n"
<< " \n"
<< " Each row corresponds to a different point.\n"
<< " \n"
<< " f is the focal lenght in pixels. \n"
<< " cx is the image principal point x coordinates in pixels. \n"
<< " cy is the image principal point y coordinates in pixels. \n"
<< "------------------------------------------------------------------\n\n"
<< endl;
}
/* Build the following structure data
*
* frame1 frame2 frameN
* track1 | (x11,y11) | -> | (x12,y12) | -> | (x1N,y1N) |
* track2 | (x21,y11) | -> | (x22,y22) | -> | (x2N,y2N) |
* trackN | (xN1,yN1) | -> | (xN2,yN2) | -> | (xNN,yNN) |
*
*
* In case a marker (x,y) does not appear in a frame its
* values will be (-1,-1).
*/
void
parser_2D_tracks(const string &_filename, std::vector<Mat> &points2d )
{
ifstream myfile(_filename.c_str());
if (!myfile.is_open())
{
cout << "Unable to read file: " << _filename << endl;
exit(0);
} else {
double x, y;
string line_str;
int n_frames = 0, n_tracks = 0;
// extract data from text file
vector<vector<Vec2d> > tracks;
for ( ; getline(myfile,line_str); ++n_tracks)
{
istringstream line(line_str);
vector<Vec2d> track;
for ( n_frames = 0; line >> x >> y; ++n_frames)
{
if ( x > 0 && y > 0)
track.push_back(Vec2d(x,y));
else
track.push_back(Vec2d(-1));
}
tracks.push_back(track);
}
// embed data in reconstruction api format
for (int i = 0; i < n_frames; ++i)
{
Mat_<double> frame(2, n_tracks);
for (int j = 0; j < n_tracks; ++j)
{
frame(0,j) = tracks[j][i][0];
frame(1,j) = tracks[j][i][1];
}
points2d.push_back(Mat(frame));
}
myfile.close();
}
}
/* Keyboard callback to control 3D visualization
*/
bool camera_pov = false;
void keyboard_callback(const viz::KeyboardEvent &event, void* cookie)
{
if ( event.action == 0 &&!event.symbol.compare("s") )
camera_pov = !camera_pov;
}
/* Sample main code
*/
int main(int argc, char** argv)
{
// Read input parameters
if ( argc != 5 )
{
help();
exit(0);
}
// Read 2D points from text file
std::vector<Mat> points2d;
parser_2D_tracks( argv[1], points2d );
// Set the camera calibration matrix
const double f = atof(argv[2]),
cx = atof(argv[3]), cy = atof(argv[4]);
Matx33d K = Matx33d( f, 0, cx,
0, f, cy,
0, 0, 1);
bool is_projective = true;
vector<Mat> Rs_est, ts_est, points3d_estimated;
reconstruct(points2d, Rs_est, ts_est, K, points3d_estimated, is_projective);
// Print output
cout << "\n----------------------------\n" << endl;
cout << "Reconstruction: " << endl;
cout << "============================" << endl;
cout << "Estimated 3D points: " << points3d_estimated.size() << endl;
cout << "Estimated cameras: " << Rs_est.size() << endl;
cout << "Refined intrinsics: " << endl << K << endl << endl;
cout << "3D Visualization: " << endl;
cout << "============================" << endl;
viz::Viz3d window_est("Estimation Coordinate Frame");
window_est.setBackgroundColor(); // black by default
window_est.registerKeyboardCallback(&keyboard_callback);
// Create the pointcloud
cout << "Recovering points ... ";
// recover estimated points3d
vector<Vec3f> point_cloud_est;
for (int i = 0; i < points3d_estimated.size(); ++i)
point_cloud_est.push_back(Vec3f(points3d_estimated[i]));
cout << "[DONE]" << endl;
cout << "Recovering cameras ... ";
vector<Affine3d> path_est;
for (size_t i = 0; i < Rs_est.size(); ++i)
path_est.push_back(Affine3d(Rs_est[i],ts_est[i]));
cout << "[DONE]" << endl;
cout << "Rendering Trajectory ... ";
cout << endl << "Press: " << endl;
cout << " 's' to switch the camera pov" << endl;
cout << " 'q' to close the windows " << endl;
if ( path_est.size() > 0 )
{
// animated trajectory
int idx = 0, forw = -1, n = static_cast<int>(path_est.size());
while(!window_est.wasStopped())
{
for (size_t i = 0; i < point_cloud_est.size(); ++i)
{
Vec3d point = point_cloud_est[i];
Affine3d point_pose(Mat::eye(3,3,CV_64F), point);
char buffer[50];
sprintf (buffer, "%d", static_cast<int>(i));
viz::WCube cube_widget(Point3f(0.1,0.1,0.0), Point3f(0.0,0.0,-0.1), true, viz::Color::blue());
cube_widget.setRenderingProperty(viz::LINE_WIDTH, 2.0);
window_est.showWidget("Cube"+string(buffer), cube_widget, point_pose);
}
Affine3d cam_pose = path_est[idx];
viz::WCameraPosition cpw(0.25); // Coordinate axes
viz::WCameraPosition cpw_frustum(K, 0.3, viz::Color::yellow()); // Camera frustum
if ( camera_pov )
window_est.setViewerPose(cam_pose);
else
{
// render complete trajectory
window_est.showWidget("cameras_frames_and_lines_est", viz::WTrajectory(path_est, viz::WTrajectory::PATH, 1.0, viz::Color::green()));
window_est.showWidget("CPW", cpw, cam_pose);
window_est.showWidget("CPW_FRUSTUM", cpw_frustum, cam_pose);
}
// update trajectory index (spring effect)
forw *= (idx==n || idx==0) ? -1: 1; idx += forw;
// frame rate 1s
window_est.spinOnce(1, true);
window_est.removeAllWidgets();
}
}
return 0;
}
I would be really grateful if someone can help me through this. Thank you.

Out of Index Error when reading Image with OpenCV using Pointer

I receive a weird out of range error when reading an 16-bit RGB image with openCV. The image has a resolution of 2700 x 2000. Outer rows and columns of the image are black.
I got the following code:
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
using namespace cv;
using namespace std;
int main( int argc, char** argv )
{
// Create Mat Container and rowPtr
Mat image;
image = imread(argv[1], -1);
uint16_t* rowPtr;
// Read Image characteristics
int width = image.cols;
int height = image.rows;
int numChannels = image.channels();
if (image.isContinuous())
{
std::cout << "isContinuous!" << "\n";
width *= height;
height = 1;
}
// Double for loop, reading using pointers according to
// https://docs.opencv.org/2.4/doc/tutorials/core/how_to_scan_images/how_to_scan_images.html
for ( uint32_t y = 0; y < height; ++y )
{
rowPtr = image.ptr<uint16_t>(y);
for ( uint32_t x = 0; x < width; ++x )
{
const uint32_t idx = x + y * width;
// Quick Debug
if (idx > 2704713)
{
std::cout << "height : " << height << "\n";
std::cout << "width : " << width << "\n";
std::cout << "row : " << y << "\n";
std::cout << "col : " << x << "\n";
std::cout << "idx : " << idx << "\n";
std::cout << "B: " << rowPtr[numChannels * idx + 0] << "\n";
std::cout << "G: " << rowPtr[numChannels * idx + 1] << "\n";
std::cout << "R: " << rowPtr[numChannels * idx + 2] << "\n"; //The error occurs here!
}
}
}
namedWindow( "Display window", WINDOW_AUTOSIZE ); // Create a window for display.
imshow( "Display window", image ); // Show our image inside it.
waitKey(0); // Wait for a keystroke in the window
return 0;
}
The output of running the code is:
isContinuous!
height : 1
width : 5400000
row : 0
col : 2704714
idx : 2704714
B: 0
G: 0
So, the segmentation fault happens, when the value for R should be read, at Pixel No. 2,704,715.
This code runs without problems for images that don't exhibit large black borders. So I thought that openCV's imread might crop such images internally, leading to such an error?

DICOM to Point Cloud in VTK

Is there any method for converting DICOM (ct scan) images to Point Clouds using VTK?
VTK allows reading DICOM and DICOM series and volume rendering but is it possible to generate a Point Cloud from a series of DICOM images?
If it isn't possible in VTK, is there some other library that I can use for this purpose?
Here is a dicom to point cloud demonstration. Dicom files are pretty variable depending on how the imaging is collected, but this is what we have been using for CT scans for some time. This is the "manual version" ie where you will need to interact with the terminal to navigate the dicom directory. It is possible to automate this but is highly dependent on your application.
I have pcl 8.0 and vtkdicom installed. (i was able to do a limited implementation of this without vtkdicom, but its features make the application far more robust at handling diverse dicom directory structures).
You will need to point the function in the main towards the appropriate directory on your computer (should be the file containing the DICOMDIR file). Once you have loaded the dicom, the visualizer has keyboard inputs m and n to control intensity target to be visualized. (you can easily change the code to filter for any of the parameters: x,y,z,intensity) and can change the width or stepsize as needed.
#include <pcl/common/common_headers.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/filters/passthrough.h>
#include <boost/thread/thread.hpp>
#include <vtkSmartPointer.h>
#include <vtkDICOMImageReader.h>
#include "vtkImageData.h"
#include "vtkDICOMDirectory.h"
#include "vtkDICOMItem.h"
#include "vtkStringArray.h"
#include "vtkIntArray.h"
#include "vtkDICOMReader.h"
bool loadDICOM(pcl::PointCloud<pcl::PointXYZI>::Ptr outCloud, std::string fullPathToDicomDir)
{
// load DICOM dir file
vtkSmartPointer<vtkDICOMDirectory> ddir =
vtkSmartPointer<vtkDICOMDirectory>::New();
ddir->SetDirectoryName(fullPathToDicomDir.c_str());
ddir->Update();
//select patient
int n = ddir->GetNumberOfPatients();
int patientSelection = 0;
if (n > 1)
{
std::cout << "Select Patient number, total count: " << n << std::endl;
std::string userInput;
std::getline(std::cin, userInput);
patientSelection = std::stoi(userInput);
}
const vtkDICOMItem& patientItem = ddir->GetPatientRecord(patientSelection);
std::cout << "Patient " << patientSelection << ": " << patientItem.Get(DC::PatientID).AsString() << "\n";
//select study
vtkIntArray* studies = ddir->GetStudiesForPatient(patientSelection);
vtkIdType m = studies->GetMaxId() + 1;
int studySelection = 0;
if (m > 1)
{
std::cout << "Select study, total count: " << m << std::endl;
std::string userInput;
std::getline(std::cin, userInput);
studySelection = std::stoi(userInput);
}
int j = studies->GetValue(studySelection);
const vtkDICOMItem& studyItem = ddir->GetStudyRecord(j);
const vtkDICOMItem& studyPItem = ddir->GetPatientRecordForStudy(j);
cout << " Study " << j << ": \""
<< studyItem.Get(DC::StudyDescription).AsString() << "\" \""
<< studyPItem.Get(DC::PatientName).AsString() << "\" "
<< studyItem.Get(DC::StudyDate).AsString() << "\n";
int k0 = ddir->GetFirstSeriesForStudy(j);
int k1 = ddir->GetLastSeriesForStudy(j);
int seriesSelection;
std::cout << "Select series, range: " << k0 << " to " << k1 << std::endl;
for (int i = k0; i <= k1; i++)
{
const vtkDICOMItem& seriesItem = ddir->GetSeriesRecord(i);
vtkStringArray* a = ddir->GetFileNamesForSeries(i);
cout << " Series " << i << ": \""
<< seriesItem.Get(DC::SeriesDescription).AsString() << "\" "
<< seriesItem.Get(DC::SeriesNumber).AsString() << " "
<< seriesItem.Get(DC::Modality).AsString() << ", Images: "
<< a->GetNumberOfTuples() << "\n";
}
std::string userInput;
std::getline(std::cin, userInput);
seriesSelection = std::stoi(userInput);
const vtkDICOMItem& seriesItem = ddir->GetSeriesRecord(seriesSelection);
cout << " Series " << seriesSelection << ": \""
<< seriesItem.Get(DC::SeriesDescription).AsString() << "\" "
<< seriesItem.Get(DC::SeriesNumber).AsString() << " "
<< seriesItem.Get(DC::Modality).AsString() << "\n";
vtkStringArray* a = ddir->GetFileNamesForSeries(seriesSelection);
vtkDICOMReader* reader = vtkDICOMReader::New();
reader->SetFileNames(a);
reader->Update();
vtkSmartPointer<vtkImageData> sliceData = reader->GetOutput();
int numberOfDims = sliceData->GetDataDimension();
int* dims = sliceData->GetDimensions();
std::cout << "Cloud dimensions: ";
int totalPoints = 1;
for (int i = 0; i < numberOfDims; i++)
{
std::cout << dims[i] << " , ";
totalPoints = totalPoints * dims[i];
}
std::cout << std::endl;
std::cout << "Number of dicom points: " << totalPoints << std::endl;
//read data into grayCloud
double* dataRange = sliceData->GetScalarRange();
double* spacingData = reader->GetDataSpacing();
std::cout << "Data intensity bounds... min: " << dataRange[0] << ", max: " << dataRange[1] << std::endl;
if (numberOfDims != 3)
{
std::cout << "Incorrect number of dimensions in dicom file, generation failed..." << std::endl;
return false;
}
else
{
Eigen::RowVector3f spacing = Eigen::RowVector3f(spacingData[0], spacingData[1], spacingData[2]);
Eigen::RowVector3i dimensions = Eigen::RowVector3i(dims[0], dims[1], dims[2]);
outCloud->points.clear();
std::cout << "x spacing: " << spacing(0) << std::endl;
std::cout << "y spacing: " << spacing(1) << std::endl;
std::cout << "z spacing: " << spacing(2) << std::endl;
for (int z = 0; z < dims[2]; z++)
{
if (z % 50 == 0)
{
double percentageComplete = (double)z / (double)dims[2];
std::cout << "Dicom Read Progress: " << (int)(100.0 * percentageComplete) << "%" << std::endl;
}
for (int y = 0; y < dims[1]; y++)
{
for (int x = 0; x < dims[0]; x++)
{
double tempIntensity = sliceData->GetScalarComponentAsDouble(x, y, z, 0);
int tempX = x;
pcl::PointXYZI tempPt = pcl::PointXYZI();
if (!isinf(tempIntensity) && !isnan(tempIntensity))
{
//map value into positive realm
//tempIntensity = ((tempIntensity - dataRange[0]) / (dataRange[1] - dataRange[0]));
if (tempIntensity > SHRT_MAX) { tempIntensity = SHRT_MAX; }
else if (tempIntensity < SHRT_MIN) { tempIntensity = SHRT_MIN; }
}
else
{
tempIntensity = 0;
}
tempPt.x = tempX;
tempPt.y = y;
tempPt.z = z;
tempPt.intensity = tempIntensity;
outCloud->points.push_back(tempPt);
}
}
}
}
std::cout << "Load Dicom Cloud Complete!" << std::endl;
return true;
}
int indexSlice = 0;
void keyboardEventOccurred(const pcl::visualization::KeyboardEvent& event, void* viewer)
{
if (event.getKeySym() == "n" && event.keyDown())
{
indexSlice -= 1;
}
else if (event.getKeySym() == "m" && event.keyDown())
{
indexSlice += 1;
}
}
void displayCloud(pcl::PointCloud<pcl::PointXYZI>::Ptr cloud, std::string field, int step, int width, std::string window_name = "default")
{
boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer(new pcl::visualization::PCLVisualizer(window_name));
viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "id");
viewer->registerKeyboardCallback(keyboardEventOccurred, (void*)viewer.get());
pcl::PointCloud<pcl::PointXYZI>::Ptr tempCloud(new pcl::PointCloud<pcl::PointXYZI>);
pcl::PassThrough<pcl::PointXYZI> pass;
pass.setInputCloud(cloud);
pass.setFilterFieldName(field); //could gate this on intensity if u preferred
int lastIndex = indexSlice-1; //proc first cycle
while (!viewer->wasStopped()) {
if (indexSlice != lastIndex)
{
int low = step * indexSlice - width / 2;
int high = step * indexSlice + width / 2;
pass.setFilterLimits(low, high);
pass.filter(*tempCloud);
lastIndex = indexSlice;
std::cout << field<< " range: " <<low<<" , "<<high<< std::endl;
viewer->removeAllPointClouds();
pcl::visualization::PointCloudColorHandlerGenericField<pcl::PointXYZI> point_cloud_color_handler(tempCloud, "intensity");
viewer->addPointCloud< pcl::PointXYZI >(tempCloud, point_cloud_color_handler, "id");
}
viewer->spinOnce(50);
}
viewer->close();
}
// --------------
// -----Main-----
// --------------
int main(int argc, char** argv)
{
pcl::PointCloud<pcl::PointXYZI>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZI>);
loadDICOM(cloud, "C:/Local Software/voyDICOM/resources/DICOM_Samples/2021APR14 MiniAchors_V0");
displayCloud(cloud,"intensity",100,50);
return 0;
}
Note that in most cases dicom files are relatively massive in terms of raw dimensions and so I very rarely (never?) have loaded a whole dicom file into a point cloud (until for this code). Generally what I do is handle it in a dense format (short array) and then create clouds based on selections from that data. This way you can do certain imaging operations that benefit from a locked data grid (opening, closing, etc) prior to going to the sparse data set (point cloud) where everything becomes profoundly more expensive.
Pretty picture of it working with one of my debug dicom sets:
I think I might have found a way, after all. Haven't tried it yet but in theory it should work.
Firstly, the DICOM image needs to be converted into .vtk format using VTK once the DICOM images have been converted into .vtk they can then be converted into .pcd (Point cloud format) using PCL (point cloud library).

Load an OpenCV::Mat as a .pgm

I have a program which loads a .PGM image file into std::vector m_data :
void LoadPgm( std::string const& filename ){
std::ifstream in( filename.c_str(), std::ios::binary );
if ( !in ){
std::cerr << "Error in Image::LoadPgm: Could not open file " << filename << std::endl;
std::exit(1);
}
std::string data = std::string( std::istreambuf_iterator< char >( in ),
std::istreambuf_iterator< char >() );
if ( ( data[0] != 'p' && data[0] != 'P' ) || data[1] != '5' ){
std::cerr << "Error in Image::LoadPgm: Unsupported image format " << filename << std::endl;
std::exit(1);
}
unsigned char const* p = reinterpret_cast< unsigned char* >(&data[2]);
m_width = ReadNumber( p );
m_height = ReadNumber( p );
if ( ReadNumber( p ) > 255 )
{
std::cerr << "Error in Image::LoadPgm: Unsupported image deep "
<< filename << std::endl;
std::exit(1);
}
p++;
m_data.assign( p, p + m_width * m_height );
}
Where the ReadNumber() is :
unsigned long ReadNumber(unsigned char const*&buffer){
do{
if ( *(buffer++) == '#' ){
while ( *(buffer++) != 10 );
}
switch (*buffer)
{
case 9 :
case 10 :
case 13 :
case ' ' :
case '#' :
case '0' :
case '1' :
case '2' :
case '3' :
case '4' :
case '5' :
case '6' :
case '7' :
case '8' :
case '9' : break;
default :
{
std::cerr << "Error in Image::LoadPgm: invalid data" << std::endl;
exit( 1 );
}
}
}
while ( (*buffer < '0') || (*buffer > '9') );
unsigned long value = 0;
do
{
value = 10 * value;
value += *(buffer++) - '0';
}
while ( (*buffer>='0') && (*buffer<='9') );
return value;
}
My question is how can I load, instead of .pgm file, an OpenCV Mat into m_data (without creating a file).
EDIT
Here is my solution (thanks to ypnos) :
void LoadPgm(cv::Mat1b &cvimg ){
Mat1b matimage;
cvtColor(cvimg, matimage, CV_RGB2GRAY);
// Create a pgm object
std::vector<unsigned char> dest(matimage.rows*matimage.cols);
std::copy(matimage.begin(), matimage.end(), dest.begin());
std::stringstream in;
in << "P5" << std::endl;
in << matimage.cols << std::endl;
in << matimage.rows << std::endl;
in << "255" << std::endl;
in.write( reinterpret_cast<char*>( &dest[0] ), matimage.cols * matimage.rows );
std::string data = std::string( std::istreambuf_iterator< char >( in ), std::istreambuf_iterator< char >() );
if ( ( data[0] != 'p' && data[0] != 'P' ) || data[1] != '5' ){
std::cerr << "Error in Image::LoadPgm: Unsupported image format " << std::endl;
std::exit(1);
}
unsigned char const* p = reinterpret_cast< unsigned char* >(&data[2]);
m_width = ReadNumber( p );
m_height = ReadNumber( p );
if ( ReadNumber( p ) > 255 ){
std::cerr << "Error in Image::LoadPgm: Unsupported image deep" << std::endl;
std::exit(1);
}
p++;
m_data.assign( p, p + m_width * m_height );
}
If you want to reliably copy all pixels of a 1 channel unsigned char matrix into an array, do this:
cv::Mat1u source = …
std::vector<unsigned char> dest(source.rows*source.cols);
std::copy(source.begin(), source.end(), dest.begin());

Resources