segmentation fault: 11, extracting data in vector - c++

I'm trying to write a program with opencv and C++. I have an image and I am trying to get the saturation value of determined pixel which is in the (x, y) point. I use the next sentence to do it:
saturation_level = hsv_chanels[1].at<uchar>(x, y);
The thing is that the program builds OK, but when I try to run, it sometimes works fine and sometimes terminates with this error:
Segmentation fault: 11
Do someone know why this error is appearing? I read that this error appears because of the my computer memory but I don't know why it only appears sometimes.
EDIT:
This is the function I call to find the homography:
Mat ObtenHomografiaSuelo (vector <KeyPoint> keypoints1, vector <KeyPoint> keypoints2, Mat imagen1, Mat imagen2){
//*****************************************************************************
//Find homography mat
//*****************************************************************************
vector < Point2f > image_points[2];
int cont = 0;
vector<Mat> chanels_hsv1; //[0]->H, [1]->S, [2]->V
split( image1, chanels_hsv1 );
vector<Mat> chanels_hsv2;
split( image2, chanels_hsv2 );
for(vector<KeyPoint>::const_iterator it = keypoints1.begin(); it!= keypoints1.end(); ++it){
// Get the position of left keypoints
float x = (it->pt.x);
float y = (it->pt.y);
cout << "1" << endl;
float saturation_level = chanels_hsv1[1].at<uchar>(x, y);
cout << "2" << endl;
double max_level = 70.0;
cout << "3" << endl;
if ((y < camSize.height/4) && (saturatio_level < max_level) ){
cout << "1:" << endl;
waitKey (100);
cout << "y: " << y;
cout << " Saturation_Level: " << nivel_saturacion << endl;
image_points[0].push_back(Point2f(x,y));
cout << "done" << endl;
cont ++;
}
}
cont = 0;
for (vector<KeyPoint>::const_iterator it = keypoints2.begin(); it!=keypoints2.end(); ++it) {
// Get the position of left keypoints
float x = (it->pt.x);
float y = (it->pt.y);
float saturation_level = chanels_hsv2[1].at<uchar>(x, y);
double max_level = 70.0;
if ((y < (camSize.height)/4) && (saturation_level < max_level)){
cout << "2" << endl;
waitKey (100);
cout << "y: " << y;
cout << " Saturation_Level: " << nivel_saturacion << endl;
image_points[1].push_back(Point2f(x,y));
cont ++;
}
}
cout << "We are obtain: " << cont << " points to do the homography" << endl;
waitKey();
Mat H;
H = Mat::zeros(4, 4, CV_64F);
if (cont < 4) {
cout << "Few points to do the homography" << endl;
}
else{
if (image_points[0].size() > image_points[1].size()){
image_points[0].resize(image_points[1].size());
}
else if (image_points[1].size() > image_points[0].size()){
image_points[1].resize(image_points[0].size());
}
H = findHomography (image_points[0], image_points[1], CV_RANSAC, 3);
cout << "done_matrix" << endl;
}
return H;
}
Before to call the function I detect keypoints using Harris or any other detector and the image I passed to the function is a HSV_image converted by cvtColor function.
The error appears in the line that I mentioned before because in the terminal I can se:
1
Segmentation Fault: 11

I've just finished to correct the error, I think it was because I wasn't using efficiently my function. I was using two 'for' staments to cross my two vectors of keypoints detected and the errors sometimes appears at first and others at second one. I don't really know why was the error, I just change my code to do the same think more efficiently and finally it works.
I just changed this lines:
for(vector<KeyPoint>::const_iterator it = keypoints1.begin(); it!= keypoints1.end(); ++it){
// Get the position of left keypoints
float x = (it->pt.x);
float y = (it->pt.y);
cout << "1" << endl;
float saturation_level = chanels_hsv1[1].at<uchar>(x, y);
cout << "2" << endl;
double max_level = 70.0;
cout << "3" << endl;
if ((y < camSize.height/4) && (saturatio_level < max_level) ){
cout << "1:" << endl;
waitKey (100);
cout << "y: " << y;
cout << " Saturation_Level: " << nivel_saturacion << endl;
image_points[0].push_back(Point2f(x,y));
cout << "done" << endl;
cont ++;
}
cont = 0;
for (vector<KeyPoint>::const_iterator it = keypoints2.begin(); it!=keypoints2.end(); ++it) {
// Get the position of left keypoints
float x = (it->pt.x);
float y = (it->pt.y);
float saturation_level = chanels_hsv2[1].at<uchar>(x, y);
double max_level = 70.0;
if ((y < (camSize.height)/4) && (saturation_level < max_level)){
cout << "2" << endl;
waitKey (100);
cout << "y: " << y;
cout << " Saturation_Level: " << nivel_saturacion << endl;
image_points[1].push_back(Point2f(x,y));
cont ++;
}
}
by this ones:
for (int i = 0; i < good_matches.size(); i++) {
int idx1=good_matches[i].queryIdx;
int idx2=good_matches[i].trainIdx;
if (((keypoints[0][idx1].pt.y < (camSize.height/4)) && (canales_hsv1[1].at<uchar>(keypoints[0][idx1].pt.x, keypoints[0][idx1].pt.y) < nivel_maximo)) || ((keypoints[1][idx2].pt.y < (camSize.height/4)) && (canales_hsv2[1].at<uchar>(keypoints[1][idx1].pt.x, keypoints[1][idx2].pt.y) < nivel_maximo)) ) {
cout << "entro" << endl;
matched_points[0].push_back(keypoints[0][idx1].pt);
matched_points[1].push_back(keypoints[1][idx2].pt);
contador ++;
}
}
Currently I only cross the matched keypoints instead of all the keypoints, it requires less computers operations and now it works OK.

Related

How to access to the values stored in a flann::Matrix

I'm working with flann library with point clouds. I have this adapter method that transform my own points to a flann-usable points
flann::Matrix<float> * converterFlann::convertArray(vector<Point *> *P){
float points[P->size()*3];
int j = 0;
for (int i = 0; i<P->size(); i++){
points[j] = P->at(i)->getX(); j++;
points[j] = P->at(i)->getY(); j++;
points[j] = P->at(i)->getZ(); j++;
}
P->at(0)->print();
cout << points[0] << " " << points[1] << " " << points[2] << endl;
flann::Matrix<float> *nari = new flann::Matrix<float>(points, P->size(), 3);
cout << *nari[0][0] << " " << *nari[0][1] << " " << *nari[0][2] << endl;
return nari;
}
And the output of this method is
Printing my point: (-0.06325, 0.0359793, 0.0420873) Index: 0
Printing from points array: -0.06325 0.0359793 0.0420873
Printing from flann: -0.06325 -0.06275 -0.0645
I don't understand why printing from flann::Matrix, Y and Z are different. I've been looking for some documentation about storing procedure of flann::Matrix but I'm not able to find any answer. I thing that my array-type access is correct but it doesn't work.
Thanks in advance. :D

segmentation fault for string function argument

I have a simple main code that gives me segmentation fault when calling a function. In the following code, I have two functions, the first one works correctly but the program doesn't enter the second one and gives me segmentation fault error. Is there any reason for that? I have made sure about the following:
The variables o and c are not out of bound.
cn is initialized correctly.
I have a read-only access to cm and argv. Plus it does not even enter the function evaluate
Here is the code:
void print_cm(vector<vector<int> > *cm, char* gtf);
void evaluate(vector<vector<int> > *cm, char* gtf);
int main(int argc, char** argv)
{
int o = 2; // It is initialized
int c = 4; // It is initialized
vector<vector<int> > cm; // It is initialized
if (argc>4)
print_cm(&cm, argv[o]);
if (argc>4)
{
cout << argv[c] << endl; // Works
// The following also works
for (int i=0; i<cm.size(); i++)
for (int j=0; j<cm[i].size(); j++)
cout << cm[i][j] << " ";
// The following causes segmentation fault;
evaluate(&cm, argv[c]);
}
return 0;
}
void evaluate(vector<vector<int> > *cm, char* gtf)
{
// Read-only access to cm and gtf
}
void print_cm(vector<vector<int> > *cm, char* gtf)
{
// Read-only access to cm and gtf
}
Here is the complete code:
#include "includes/Utility.h"
#include "includes/Graph.h"
void print_cm(vector<vector<int> > *cores, char* output);
void evaluate(vector<vector<int> > const *cm, char* gtf);
int main(int argc, char** argv)
{
int g = -1, c = -1, o = -1;
for (int i=1; i<argc-1; i++)
if (argv[i][0]=='-')
{
if (argv[i][1]=='g')
g = i + 1;
else if (argv[i][1]=='c')
c = i + 1;
else if (argv[i][1]=='k')
ki = i + 1;
else if (argv[i][1]=='s')
si = i + 1;
else if (argv[i][1]=='o')
o = i + 1;
}
Graph G;
if (c>0) G.read_input(argv[g], argv[c]);
else G.read_input(argv[g]);
if (ki > 0)
{
int k = atoi(argv[ki]);
cout << k << endl;
}
if (si > 0)
{
int s = atoi(argv[si]);
cout << s << endl;
}
// Find communities
vector<vector<int> > cores;
G.partitioning(&cores);
if (o>0)
print_cm(&cores, argv[o]);
if (c>0)
{
cout << "here" << endl;
for (size_t i=0; i<cores.size(); i++)
for (size_t j=0; j<cores[i].size(); j++)
if (cores.at(i).at(j)<0) cout << "here";
cout << "here" << endl;
evaluate(&cores, argv[c]);
}
}
return 0;
}
void print_cm(vector<vector<int> > *cores, char* output)
{
ofstream out;
out.open(output);
for(size_t i=0; i<(*cores).size(); i++)
{
for(size_t j=0; j<(*cores)[i].size(); j++)
out << (*cores)[i][j] << " ";
out << endl;
}
out.close();
return ;
}
void evaluate(vector<vector<int> > const *cm, char* gtf)
{
// we evaluate precision, recall, F1 and F2
vector<vector<int> > gt;
ifstream in;
char str[100000000];
in.open(gtf);
while(in.getline(str, 100000000))
{
stringstream s;
s << str;
int a;
gt.resize(gt.size()+1);
while (s >> a) gt[gt.size()-1].push_back(a);
}
in.close();
cout << "==================== Evaluation Results ====================" << endl;
int imax = 0;
for(size_t i=0; i<(*cm).size(); i++)
imax = max(imax, *max_element((*cm)[i].begin(), (*cm)[i].end()));
for(size_t i=0; i<gt.size(); i++)
imax = max(imax, *max_element(gt[i].begin(), gt[i].end()));
vector<bool> flag(imax, false);
vector<double> recall((*cm).size(), 0), precision((*cm).size(), 0), f1((*cm).size(), 0), f2((*cm).size(), 0);
int overlap;
double size = 0;
for(size_t i=0; i<(*cm).size(); i++)
{
// evaluate
size += (double) (*cm)[i].size();
for(size_t j=0; j<(*cm)[i].size(); j++)
flag[(*cm)[i][j]] = true;
double p, r, ff1, ff2;
for(size_t j=0; j<gt.size(); j++)
{
overlap = 0;
for(size_t k=0; k<gt[j].size(); k++)
if (flag[gt[j][k]]) overlap++;
p = (double) overlap / (double) (*cm)[i].size();
if (p > precision[i])
precision[i] = p;
r = (double) overlap / (double) gt[j].size();
if (r > recall[i])
recall[i] = r;
ff1 = (double) 2*(p*r)/(p+r);
if (ff1 > f1[i])
f1[i] = ff1;
ff2 = (double) 5*(p*r)/(4*p + r);
if (ff2 > f2[i])
f2[i] = ff2;
}
for(size_t j=0; j<(*cm)[i].size(); j++)
flag[(*cm)[i][j]] = false;
}
double Recall = 0, Precision = 0, F1 = 0, F2 = 0;
for(size_t i=0; i<(*cm).size(); i++)
{
Recall += recall[i];
Precision += precision[i];
F1 += f1[i];
F2 += f2[i];
}
cout << "+--------------+--------------+--------------+--------------+" << endl;
cout << "| " << setiosflags( ios::left ) << setw(10) << "Precision";
cout << " | " << setiosflags( ios::left ) << setw(10) << "Recall";
cout << " | " << setiosflags( ios::left ) << setw(10) << "F1-measure";
cout << " | " << setiosflags( ios::left ) << setw(10) << "F2-measure";
cout << " |" << endl;
cout << "| " << setiosflags( ios::left ) << setw(10) << Precision/(*cm).size() ;
cout << " | " << setiosflags( ios::left ) << setw(10) << Recall/(*cm).size();
cout << " | " << setiosflags( ios::left ) << setw(10) << F1/(*cm).size();
cout << " | " << setiosflags( ios::left ) << setw(10) << F2/(*cm).size();
cout << " |" << endl;
cout << "+--------------+--------------+--------------+--------------+" << endl;
cout << "Number of communities: " << (*cm).size() << endl;
cout << "Average community size: " << size/(*cm).size() << endl;
return ;
}
char str[100000000];
This is in your evaluate function. This are 100 million bytes, or about 95 MB that you're allocating on the stack.
Typical stack sizes are far less than that, around 1 MB.
So apart from possible other problems this is most likely causing a stack overflow.
When entering the function, the stack frame gets extended to be large enough to hold the local variables. As soon as the stack is used then (to write a default value) you're accessing invalid (non stack, thankfully protected) memory.

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.

C++: Copying an element from an unordered_set to a vector

Background: I am implementing the nearest neighbor algorithm for the Traveling-Salesman-Problem. I need to calculate the distance traveled for the tour as well as keep track of the order of points visited. I have defined a point class with instance variables x and y and a function calcDist for calculating the distance between two points. I start by storing all of the points in a std::unordered_set named points, creating an empty std::vector named path to store the tour path, and assigning the starting point to startPoint, and pass these to my nearestNeighbor() function:
void nearestNeighbor(unordered_set<Point, PointHasher> points, vector<Point> &path, Point startPoint) {
// Declare variables
unordered_set<Point, PointHasher>::iterator it;
Point currentLocation, possibleNeighbor, nearestNeighbor;
double totalDist = 0;
int pointsCount = path.capacity() - 1;
// Set the starting location
it = points.find(startPoint);
currentLocation = *it;
path[0] = currentLocation;
points.erase(currentLocation);
cout << "Start location: " << path[0].x << ", " << path[0].y << endl;
// Create the path
for (int i = 1; points.size() > 0; i++) {
double minDist = -1;
// Find the current location's nearest neighbor
for (it = points.begin(); it != points.end(); it++) {
possibleNeighbor = *it;
int currentDist = currentLocation.calcDist(possibleNeighbor);
if (minDist == -1 || currentDist < minDist) {
minDist = currentDist;
nearestNeighbor = possibleNeighbor;
}
}
// Record nearest neighbor data and prepare for the next iteration
currentLocation = nearestNeighbor;
path[i] = currentLocation;
points.erase(currentLocation);
totalDist += minDist;
cout << "Nearest neighbor: " << path[i].x << ", " << path[i].y << endl;
}
// Return to the starting location
path[pointsCount] = startPoint;
cout << "End location: " << startPoint.x << ", " << startPoint.y << endl;
cout << "Path:" << endl;
for (int i = 0; i < path.size(); i++) {
cout << path[0].x << ", " << path[0].y << endl;
}
cout << "Total distance: " << totalDist << endl;
}
The problem is that once the program exits the outer for loop, all the points in path are overwritten somehow. To see what I mean, here is the output:
Start location: 3, 4
Nearest neighbor: 6, 8
Nearest neighbor: 11, 7
Nearest neighbor: 50, 8
End location: 3, 4
Path:
3, 4
3, 4
3, 4
3, 4
3, 4
Total distance: 49
Press any key to continue . . .
I am thinking this either has to be a problem with pointers/addresses of the vector elements, or something with scope since the problem happens after exiting the for loop. I have even tried printing the path[1] after each iteration to see when it gets changed, but it is correct throughout the loop, and only changes in the output at the end. Any thoughts? I am stumped. And if you have made it this far, thank you very much for your time.
you are always outputing the coordinates of path[0] man
for (int i = 0; i < path.size(); i++) {
cout << path[0].x << ", " << path[0].y << endl;
}
You have
for (int i = 0; i < path.size(); i++) {
cout << path[0].x << ", " << path[0].y << endl;
}
This doesn't iterate through i. Change your 0 to i and you'll likely see something more helpful:
for (int i = 0; i < path.size(); i++) {
cout << path[i].x << ", " << path[i].y << endl;
}
Edit: Change path[i] = currentLocation; to path.push_back(currentLocation); - this will automatically increase the size of your path vector to fit the new elements.
void nearestNeighbor(
unordered_set<Point, PointHasher> points,
vector<Point> &path,
Point startPoint,
double &totalDist) // note the new variable passed here
{
// Declare variables
unordered_set<Point, PointHasher>::iterator it;
Point currentLocation, possibleNeighbor, nearestNeighbor;
// double totalDist = 0; Remove this line
// int pointsCount = path.capacity() - 1; And this
// Set the starting location
it = points.find(startPoint);
currentLocation = *it;
path.push_back(currentLocation); // Changed this line
points.erase(currentLocation);
cout << "Start location: " << path[0].x << ", " << path[0].y << endl;
// Create the path
for (int i = 1; points.size() > 0; i++) {
double minDist = -1;
// Find the current location's nearest neighbor
for (it = points.begin(); it != points.end(); it++) {
possibleNeighbor = *it;
int currentDist = currentLocation.calcDist(possibleNeighbor);
if (minDist == -1 || currentDist < minDist) {
minDist = currentDist;
nearestNeighbor = possibleNeighbor;
}
}
// Record nearest neighbor data and prepare for the next iteration
currentLocation = nearestNeighbor;
path.push_back(currentLocation); // And this line
points.erase(currentLocation);
totalDist += minDist;
cout << "Nearest neighbor: " << path[i].x << ", " << path[i].y << endl;
}
// Return to the starting location
path.push_back(startPoint); // And here also!
cout << "End location: " << startPoint.x << ", " << startPoint.y << endl; // This I didn't change,
// but perhaps you should make it reflect the last point in the vector,
// not the start point which is supposed to be the last point in the vector
cout << "Path:" << endl;
for (int i = 0; i < path.size(); i++) {
cout << path[i].x << ", " << path[i].y << endl;
}
cout << "Total distance: " << totalDist << endl;
}
I do not see any place which grows the size of the path vector.
I suspect that you're passing an empty std::vector, for the second argument, and as soon as you hit path[0]=currentLocation; ... undefined behavior.
Also, I don't think that capacity() does what you think it does.
That, and, as others have pointed out, you're not outputing the contents of the array correctly, but that's a minor problem. The major problem here is that this program is likely scribbling over and corrupting the heap.

C++ how to load a 16bit TIFF file in a container to perform math operations on its data?

I have writtent a small C++ console application with code::blocks that loads
an array of values from a CSV file, performs a special "inverted" random dithering on the values, and exports the result as a PBM file (a bitmap).
The density of black pixels on the final PBM picture depends on 3 independent variables: "Reflectance of the white", "Reflectance of the black", and the values of the CSV.
The reason I use a CSV file is because I don't know how I can directly load a TIFF file into my script. The values of my file "wall.csv" are produced by a python script that transforms any tiff file in a csv...
Could you please check my code and advise for a solution to load a TIFF and detect automatically the size of the image in pixels?
The variables colo and lines define the size of the image contained as ASCII data in the CSV...
And the image values are loaded in the vector <float> CSV
What library would you use to load the tiff?
Thanks!
code:
#include <deque>
#include <cmath>
#include <iostream>
#include <fstream>
#include <algorithm>
#include <random>
#include <cstdlib>
using namespace std;
deque <float> CSV; // CSV input values, "PHOTOMETRY"
deque <float> RND; // will contain random values from 0.0 to 1.0
int colo = 0; // variables inputed
int lines = 0; // lines
float YBK = 0; // Reflectance White
float YW = 0; // Reflectance Black
float Lmax = 0; // variables to be computed
float Lmin = 10000000; // arbitrarily high value
float NBK = 0; // will contain a normalized Black value
float NW = 1; // normalized white value
float CRATIO = 0; // Black to White dynamic ratio
float LRATIO = 0; // Lowest to Highest pixel value dynamic ratio
float Z = 0; // processing variables
float X = 0;
float aBK = 0; // computed density of black at each pixel
float vRND = 0; // random value container
float IO = 0;
int main(){
cout << "please put a file named wall.csv" << endl << "in the same forler as this executable" << endl << endl;
cout << "how many:" << endl << "columns does the CSV has?" << endl;
cin >> colo;
cout << "lines does the CSV has?" << endl;
cin >> lines;
cout << "reflectance of the WHITE (CIE Y)?" << endl;
cin >> YW;
cout << "reflectance of the BLACK (CIE Y)?" << endl;
cin >> YBK;
NBK = YBK / YW; // normalized BK
CRATIO = NW / NBK; // correction Ratio
int C = lines * colo; // cells
cout << endl << " there are: " << colo << " columns";
cout << endl << " and : " << lines << " lines " ;
cout << endl << " that makes " << C << " cells " << endl;
cout << endl << " correction ratio is: " << CRATIO << endl << endl;
///_____ IMPORT THE PHOTOMETRIC DATA
cout << "...importing the photometric data" << endl;
float x = 0; // a variable that will contain a value from the file
ifstream ifs ("wall.csv");
char dummy;
for (int i = 0; i < lines; ++i){
for (int i = 0; i < colo; ++i){
ifs >> x;
if (x > Lmax) {
Lmax = x; // determines the highest pixel value
}
if (x < Lmin) {
Lmin = x; // determines the lowest pixel value
}
CSV.push_back(x);
// So the dummy won't eat digits
if (i < (colo - 1))
ifs >> dummy;
}}
ifstream ifs_close();
LRATIO = Lmax / Lmin;
cout << "...photometric data imported" << endl;
cout << endl << " maximum Luminance is: " << Lmax;
cout << endl << " minimum Luminance is: " << Lmin << endl;
cout << endl << "...luminance ratio is: " << LRATIO;
if (LRATIO > CRATIO) {
cout << endl << "...luminance ratio is: " << LRATIO;
cout << endl << "...this is too high, ending..." << '\a';
return(0);
}
cout << endl << "...luminance can be corrected :)" << endl;
///______ CREATE RANDOM VALUES BETWEEN 0 & 1
std::default_random_engine generator;
std::uniform_real_distribution <double> distribution(0.0,1.0);
for (int i=0; i<C; ++i) {
double number = distribution(generator);
RND.push_back(number);
}
cout << endl << "...random values created" << endl;
///_______ process & export to PBM
ofstream output_file("./wall.pbm");
output_file << "P1" << "\n" << colo << " " << lines << "\n"; /// PBM HEADER
cout << endl << "...file header written" << endl;
cout << endl << "...computing";
int CELLS = C; // copy the amount of cells
int LINEW = colo;
int PERCENT = 100;
while (CELLS > 0) {
while (LINEW > 0) {
Z = Lmin/CSV.front(); /// processing calculus
X = (NBK - Z)/(NBK - NW);
aBK = (1 - X);
vRND = RND.front();
if (aBK > (vRND)) {
IO = 1;
}
else {
IO = 0;
}
LINEW = LINEW - 1;
CELLS = CELLS - 1;
PERCENT = PERCENT - CELLS / C;
output_file << IO << "\n";
//cout << ERR << " "; /// fancy...
CSV.erase(CSV.begin());
RND.erase(RND.begin());
}
LINEW = colo;
}
cout << endl << "...computing done" << endl;
cout << "...file written";
output_file.close();
return(0);
}
Check out lib tiff. OpenCV just uses lib tiff as well.
http://www.libtiff.org/