You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

777 lines
21 KiB
C++

/*
* image implementation
*
* Copyright (C) Dorit Borrmann
*
* Released under the GPL version 3.
*
*/
#include "shapes/image.h"
#include "slam6d/globals.icc"
#include <limits>
#include <algorithm>
#include <string>
#include <fstream>
using std::string;
using std::ofstream;
#include <set>
using std::set;
#include <iterator>
using std::insert_iterator;
Image::Image(float _minw, float _maxw, float _minh, float _maxh, float
_resolution, const vector <Point> *points) {
minh = _minh;
minw = _minw;
maxh = _maxh;
maxw = _maxw;
width = (maxw - minw)/_resolution + 1;
height = (maxh - minh)/_resolution + 1;
int size = points->size();
data = new float*[width];
for(int i = 0; i < width; i++) {
data[i] = new float[height];
for(int j = 0; j < height; j++) {
data[i][j] = 0.0;
}
}
if(points != 0) {
double *tmpp = new double[3];
double reflectance;
double * polar = new double[3];
for(int i = 0; i < size; i++) {
Point p = (*points)[i];
tmpp[0] = p.x;
tmpp[1] = p.z;
tmpp[2] = p.y;
reflectance = p.reflectance;
//tmpp = points[i];
// phi theta rho
// theta = width, phi = height, rho = distance value
toPolar(tmpp, polar);
int w_i = (int)((double)((deg(polar[1]) + 90.0) - minw)/(double)(maxw - minw) * (double)width) % width;
//int w_i = ((double)((int)(deg(polar[1]) + 90)%360 - minw)/(double)(maxw - minw)) * (double)width;
if(w_i < 0) {
w_i = 0;
} else if(w_i >= width) {
w_i = width - 1;
}
int h_i = (int)((double)(deg(polar[0]) - minh)/(double)(maxh - minh) * (double)height);
if(h_i < 0) {
h_i = 0;
} else if(h_i >= height) {
h_i = height - 1;
}
if((fabs(data[w_i][h_i]) < 0.000001) || (data[w_i][h_i] < p.reflectance)) {
data[w_i][h_i] = (float)reflectance;
//cout << data[w_i][h_i] << " " << endl;
}
/*
if((fabs(data[w_i][h_i]) < 0.000001) || (data[w_i][h_i] > polar[2])) {
data[w_i][h_i] = (float)reflectance;
//cout << data[w_i][h_i] << " " << endl;
}
*/
}
delete[] tmpp;
delete[] polar;
}
}
Image::Image(float _minw, float _maxw, float _minh, float _maxh, float _resolution, double * const* points, int size) {
minh = _minh;
minw = _minw;
maxh = _maxh;
maxw = _maxw;
width = (maxw - minw)/_resolution + 1;
height = (maxh - minh)/_resolution + 1;
data = new float*[width];
for(int i = 0; i < width; i++) {
data[i] = new float[height];
for(int j = 0; j < height; j++) {
data[i][j] = 0.0;
}
}
if(points != 0) {
double *tmpp = new double[3];
double * polar = new double[3];
for(int i = 0; i < size; i++) {
tmpp[0] = points[i][0];
tmpp[1] = points[i][2];
tmpp[2] = points[i][1];
//tmpp = points[i];
// phi theta rho
// theta = width, phi = height, rho = distance value
toPolar(tmpp, polar);
int w_i = (int)((double)((deg(polar[1]) + 90.0) - minw)/(double)(maxw - minw) * (double)width) % width;
//int w_i = ((double)((int)(deg(polar[1]) + 90)%360 - minw)/(double)(maxw - minw)) * (double)width;
if(w_i < 0) {
w_i = 0;
} else if(w_i >= width) {
w_i = width - 1;
}
int h_i = (int)((double)(deg(polar[0]) - minh)/(double)(maxh - minh) * (double)height);
if(h_i < 0) {
h_i = 0;
} else if(h_i >= height) {
h_i = height - 1;
}
if((fabs(data[w_i][h_i]) < 0.000001) || (data[w_i][h_i] > polar[2])) {
data[w_i][h_i] = (float)polar[2];
//cout << data[w_i][h_i] << " " << endl;
}
}
delete[] tmpp;
delete[] polar;
}
}
Image::Image(float _minw, float _maxw, float _minh, float _maxh, float _resolution, const vector<double*> *points) {
//TODO correct this!!!
minh = _minh;
minw = _minw;
maxh = _maxh;
maxw = _maxw;
width = (maxw - minw)/_resolution + 1;
height = (maxh - minh)/_resolution + 1;
data = new float*[width];
for(int i = 0; i < width; i++) {
data[i] = new float[height];
for(int j = 0; j < height; j++) {
data[i][j] = 0.0;
}
}
if(points != 0) {
double *tmpp;
double * polar = new double[3];
for(int i = 0; i < points->size(); i++) {
tmpp = new double[3];
//tmpp = (*points)[i];
tmpp[0] = (*points)[i][0];
tmpp[1] = (*points)[i][2];
tmpp[2] = (*points)[i][1];
// phi theta rho
// theta = width, phi = height, rho = distance value
toPolar(tmpp, polar);
int w_i = (((int)(deg(polar[1]) + 180)%360 - minw)/(maxw - minw)) * width;
w_i = (((int)(deg(polar[1]) ) - minw)/(maxw - minw)) * width;
if(w_i < 0) {
w_i = 0;
} else if(w_i >= width) {
w_i = width - 1;
}
int h_i = (((int)(deg(polar[0]) + 90)%180 - minh)/(maxh - minh)) * height;
h_i = (((int)(deg(polar[0]) ) - minh)/(maxh - minh)) * height;
if(h_i < 0) {
h_i = 0;
} else if(h_i >= height) {
h_i = height - 1;
}
if((fabs(data[w_i][h_i] - 0.0) < 0.000100) || (data[w_i][h_i] > polar[2])) {
data[w_i][h_i] = (float)polar[2];
}
}
}
for(int j = 0; j < height; j++) {
for(int i = 0; i < width; i++) {
cout << data[i][j] << " " ;
}
cout << endl;
}
}
Image::~Image() {
for(int i = 0; i < width; i++) {
delete[] data[i];
}
delete[] data;
}
int Image::getWidth() {
return width;
}
int Image::getHeight() {
return height;
}
float Image::getValueAt(int width, int height) {
return data[width][height];
}
float Image::getMin() {
float min = std::numeric_limits<float>::max();
for(int i = 0; i < width; i++) {
for(int j = 0; j < height; j++) {
min = std::min(min, data[i][j]);
}
}
return min;
}
float Image::getMax() {
float max = std::numeric_limits<float>::min();
for(int i = 0; i < width; i++) {
for(int j = 0; j < height; j++) {
max = std::max(max, data[i][j]);
}
}
return max;
}
void Image::mergeregion(int x, int y, int delreg, int targetreg, int** img, int it) {
cout << x << " " << y << " " << delreg << " " << targetreg << " " << it << endl;
// traversed more than necessary
if(it > 0) return;
// cout << (j % width) << ", " << j / width << " " << width << " " << old<< " ->> " << targetreg << endl;
img[x][y] = targetreg;
cout << "A" << endl;
// left
if ( x > 0 && (img[x - 1][y] == delreg)){
cout << "1" << endl;
mergeregion(x-1, y ,delreg, targetreg, img);
cout << "2" << endl;
}
cout << "B" << endl;
// right
if ( x < width - 1 && (img[x + 1][y] == delreg)){
mergeregion(x+1, y, delreg, targetreg, img);
}
cout << "C" << endl;
// up
if ( y > 0 && (img[x][y-1] == delreg )) {
mergeregion(x, y - 1, delreg, targetreg, img);
}
cout << "D" << endl;
// down
if ( y + 1 < height && (img[x][y+1] == delreg )) {
mergeregion(x, y + 1, delreg, targetreg, img);
}
cout << "E" << endl;
}
int Image::calcMarker(float _threshold, int ** regdat) {
// segment picture
threshold = _threshold;
cout << threshold << " ";
int counter = 0;
for(int y = 0; y < height; y++) {
for(int x = 0; x < width; x++) {
if(data[x][y] > threshold) {
counter++;
regdat[x][y] = 100;
//data[x][y] = 100;
} else {
regdat[x][y] = 0;
//data[x][y] = 0;
}
}
}
//printScans(regdat, height, width)
//printImage("marker.ppm", false, regdat, height, width, 0, 1);
printImage("marker.ppm", false, regdat, height, width, 0, 100);
cout << counter << endl;
return counter;
}
int Image::cluster(float dist, int ** dat, int ** regdat) {
vector<set<int> > linked;
int up, left;
int region = 0;
for(int y = 0; y < height; y++) {
for(int x = 0; x < width; x++) {
float value = dat[x][y];
if(value != 0) {
// left border
if(x==0) {
left = value + dist*2.0;
} else {
left = dat[x-1][y];
}
// upper border
if(y==0) {
up = value + dist*2.0;
} else {
up = dat[x][y-1];
}
if (fabs(left - value) > dist) {
if (fabs(up - value) > dist) {
regdat[x][y] = ++region; // new region
set<int> *joined = new set<int>;
joined->insert(region);
linked.push_back(*joined);
} else {
regdat[x][y] = regdat[x][y - 1]; // use upper region
}
} else if (fabs(up - value) > dist) {
regdat[x][y] = regdat[x-1][y]; // use left region
} else {
// merge left and upper region, default to lower regioning number
if (regdat[x][y - 1] == regdat[ x - 1][y]) {
regdat[x][y] = regdat[x-1][y];
continue; // already same region, nothing to do
}
/*
int minreg, maxreg;
falschrum??
minreg = regdat[x][y - 1];
maxreg = regdat[x - 1][y];
*/
int up = regdat[x][y - 1];
int left = regdat[x - 1][y];
regdat[x][y] = up;
set<int> current;
set<int> *joined = new set<int>;
joined->insert(up);
joined->insert(left);
for(vector<set<int> >::iterator itr = linked.begin(); itr != linked.end(); ) {
current = (*itr);
if(current.find(up) != current.end() || current.find(left) != current.end()) {
set<int> *newjoined = new set<int>();
insert_iterator<set<int> > res_ins(*newjoined, newjoined->begin());
set_union(joined->begin(), joined->end(), current.begin(), current.end(), res_ins);
joined->clear();
delete joined;
joined = newjoined;
itr=linked.erase(itr);
} else {
itr++;
}
}
linked.push_back(*joined);
}
}
}
}
cout << region << " " << linked.size();
int linkedindex[region+1];
linkedindex[0] = 0;
set<int> current;
int link = 0;
for(vector<set<int> >::iterator itr = linked.begin(); itr != linked.end(); itr++) {
current = (*itr);
for(set<int>::iterator sitr = current.begin();
sitr != current.end();
sitr++) {
linkedindex[*sitr] = link;
}
link++;
}
cout << "Regions " << linked.size() << endl;
/*
for(int i = 0; i <= region; i++) {
cout << i << " " << linkedindex[i] << endl;
}
*/
for(int y = 0; y < height; y++) {
for(int x = 0; x < width; x++) {
regdat[x][y] = linkedindex[regdat[x][y]];
}
}
printImage("cluster.ppm", false, regdat, height, width, 0, linked.size());
return linked.size();
}
void Image::writeCenters(int regions, int** cluster, const vector<Point> *points) {
int size = points->size();
vector<Point> clusters[regions];
/*
vector<vector<Point> > clusters;
for(int i = 0; i < regions; i++) {
vector<Point> tmp = new vector<Point>();
clusters.push_back(tmp);
}
cout << "Regions: " << regions << " " << clusters.size() << endl;;
for(int i = 0; i < regions; i++) {
cout << i << " " << clusters[i]->size() << endl;
Point p = *clusters[i][0];
cout << p.x << " " << p.y << " " << p.z << endl;
}
cout << "done" << endl;
*/
/*
for(int i = 0; i < regions; i++) {
vector<Point> *tmp = new vector<Point>();
clusters[i].push_back(tmp);
}
*/
if(points != 0) {
double *tmpp = new double[3];
double reflectance;
double * polar = new double[3];
for(int i = 0; i < size; i++) {
Point p = (*points)[i];
tmpp[0] = p.x;
tmpp[1] = p.z;
tmpp[2] = p.y;
reflectance = p.reflectance;
//tmpp = points[i];
// phi theta rho
// theta = width, phi = height, rho = distance value
if(reflectance > threshold) {
toPolar(tmpp, polar);
int w_i = (int)((double)((deg(polar[1]) + 90.0) - minw)/(double)(maxw - minw) * (double)width) % width;
//int w_i = ((double)((int)(deg(polar[1]) + 90)%360 - minw)/(double)(maxw - minw)) * (double)width;
if(w_i < 0) {
w_i = 0;
} else if(w_i >= width) {
w_i = width - 1;
}
int h_i = (int)((double)(deg(polar[0]) - minh)/(double)(maxh - minh) * (double)height);
if(h_i < 0) {
h_i = 0;
} else if(h_i >= height) {
h_i = height - 1;
}
int tmp = cluster[w_i][h_i] - 1;
if(cluster[w_i][h_i] != 0) {
clusters[tmp].push_back(p);
}
}
}
delete[] tmpp;
delete[] polar;
}
cout << "Regions: " << regions << " " << clusters->size() << endl;
int markercounter = 0;
for(int i = 0; i < regions; i++) {
//cout << i << " " << clusters[i].size() << endl;
double point[3];
point[0] = point[1] = point[2] = 0;
for(int j = 0; j < clusters[i].size(); j++) {
point[0] += clusters[i][j].x;
point[1] += clusters[i][j].y;
point[2] += clusters[i][j].z;
}
for(int j = 0; j < 3; j++) {
point[j] /= clusters[i].size();
}
//cout << p.x << " " << p.y << " " << p.z << endl;
cout << point[0] << " " << point[1] << " " << point[2] << " TP" << to_string(markercounter, 4) << endl;
markercounter++;
}
}
int Image::blobColor(float dist, int ** regdat) {
// segment picture
int region = 0; // start at 12 to incresae visibility
float up, left;
for(int y = 0; y < height; y++) {
for(int x = 0; x < width; x++) {
float value = data[x][y];
// left border
if (x == 0 ) {
left = value + dist*2.0;
} else {
left = data[x - 1][y];
}
// or upper border
if ( y == 0) {
up = value + dist*2;
} else {
up = data[x][y - 1];
}
if (fabs(left - value) > dist) {
if (fabs(up - value) > dist) {
regdat[x][y] = ++region; // new region
} else {
regdat[x][y] = regdat[x][y - 1]; // use upper region
}
} else if (fabs(up - value) > dist) {
regdat[x][y] = regdat[x-1][y]; // use left region
} else {
// merge left and upper region, default to lower regioning number
if (regdat[x][y - 1] == regdat[ x - 1][y]) {
regdat[x][y] = regdat[x-1][y];
continue; // already same region, nothing to do
}
int minreg, maxreg;
/*
falschrum??
minreg = regdat[x][y - 1];
maxreg = regdat[x - 1][y];
*/
maxreg = regdat[x][y - 1];
minreg = regdat[x - 1][y];
regdat[x][y] = maxreg;
cout << "mergeRegion" << endl;
mergeregion(x, y, maxreg, minreg, regdat);
cout << "mergeRegion done" << endl;
}
}
}
cout << "color done" << endl;
//printScans(regdat, height, width)
printImage("bla.ppm", false, regdat, height, width, 1.0, region);
return region;
}
void kMeans(float dist, int ** regdat) {
}
void EM(float dist, int ** regdat) {
}
void normalizedCuts(float dist, int ** regdat) {
}
void lineMerge() {
}
void Image::printScans(int ** regdat, double * const* points, int size) {
int max_i = 0;
for(int i = 0; i < width; i++) {
for(int j = 0; j < height; j++) {
max_i = max_i > regdat[i][j] ? max_i : regdat[i][j];
}
}
cout << "size " << size << endl;
cout << "max_i is " << max_i << endl;
vector<double*> clusters[max_i + 1];
if(points != 0) {
cout << "points" << endl;
double *tmpp = new double[3];
double * polar = new double[3];
for(int i = 0; i < size; i++) {
tmpp[0] = points[i][0];
tmpp[1] = points[i][2];
tmpp[2] = points[i][1];
//tmpp = points[i];
// phi theta rho
// theta = width, phi = height, rho = distance value
toPolar(tmpp, polar);
int w_i = (int)((double)((deg(polar[1]) + 90.0) - minw)/(double)(maxw - minw) * (double)width) % width;
//int w_i = ((double)((int)(deg(polar[1]) + 90)%360 - minw)/(double)(maxw - minw)) * (double)width;
if(w_i < 0) {
w_i = 0;
} else if(w_i >= width) {
w_i = width - 1;
}
int h_i = (int)((double)(deg(polar[0]) - minh)/(double)(maxh - minh) * (double)height);
if(h_i < 0) {
h_i = 0;
} else if(h_i >= height) {
h_i = height - 1;
}
//cout << i << " " << regdat[w_i][h_i] << endl;
clusters[regdat[w_i][h_i]].push_back(points[i]);
}
delete[] tmpp;
delete[] polar;
cout << "clustering done " << endl;
string clusteroutname = "";
int index = 0;
for(int i = 0; i < max_i; i++) {
if(clusters[i].size() > 0) {
clusteroutname = "clusters/scan" + to_string(index, 3) + ".3d";
index++;
ofstream clusterout(clusteroutname.c_str());
clusterout << i << endl;
for(int j = 0; j < clusters[i].size(); j++) {
clusterout << clusters[i][j][0] << " "
<< clusters[i][j][1] << " " << clusters[i][j][2] << endl;
}
clusterout.close();
clusterout.clear();
}
}
}
}
void Image::printImage(const char* filename, bool color, int** img, int height, int width, int min, int max) {
double Fact = 255.0 /(max - min);
std::ofstream outfile(filename);
if(outfile.good()) {
if(!color) {
outfile << "P2\n" << width << " " << height << std::endl << "255" << endl;
} else {
outfile << "P3\n" << width << " " << height << std::endl << "255" << endl;
}
for(int j = 0; j < height; j++) {
for(int i = 0; i < width; i++) {
short gray = std::min(std::max((int)(Fact * (img[i][j] - min)), 0), 255);
if(!color) {
outfile << gray << " ";
} else {
double h = 255.0-gray;
double v = 1.0;
double s = 1.0;
double r = 0, g = 0, b = 0;
double h1 = h/60.0;
int i = (int)h1;
double f = h1 - i;
double pv = v * (1-s);
double qv = v * (1-s*f);
double tv = v * (1-s*(1-f));
switch(i) {
case 0:
r = v;
g = tv;
b = pv;
break;
case 1:
r = qv;
g = v;
b = pv;
break;
case 2:
r = pv;
g = v;
b = tv;
break;
case 3:
r = pv;
g = qv;
b = v;
break;
case 4:
r = tv;
g = pv;
b = v;
break;
case 5:
r = v;
g = pv;
b = qv;
break;
case 6:
r = v;
g = tv;
b = pv;
break;
default:
break;
}
outfile << (int)(r*255.0) << " " << (int)(g*255.0) << " " << (int)(b*255.0) << " ";
}
}
outfile << std::endl;
}
}
outfile.close();
}
void Image::printImage(const char *filename, bool color) {
float min = getMin();
float max = getMax();
double Fact = 255.0 /(max - min);
std::ofstream outfile(filename);
if(outfile.good()) {
if(!color) {
outfile << "P2\n" << width << " " << height << std::endl << "255" << endl;
} else {
outfile << "P3\n" << width << " " << height << std::endl << "255" << endl;
}
for(int j = 0; j < height; j++) {
for(int i = 0; i < width; i++) {
short gray = std::min(std::max((int)(Fact * (data[i][j] - min)), 0), 255);
if(!color) {
outfile << gray << " ";
} else {
double h = 255.0-gray;
double v = 1.0;
double s = 1.0;
double r = 0, g = 0, b = 0;
double h1 = h/60.0;
int i = (int)h1;
double f = h1 - i;
double pv = v * (1-s);
double qv = v * (1-s*f);
double tv = v * (1-s*(1-f));
switch(i) {
case 0:
r = v;
g = tv;
b = pv;
break;
case 1:
r = qv;
g = v;
b = pv;
break;
case 2:
r = pv;
g = v;
b = tv;
break;
case 3:
r = pv;
g = qv;
b = v;
break;
case 4:
r = tv;
g = pv;
b = v;
break;
case 5:
r = v;
g = pv;
b = qv;
break;
case 6:
r = v;
g = tv;
b = pv;
break;
default:
break;
}
outfile << (int)(r*255.0) << " " << (int)(g*255.0) << " " << (int)(b*255.0) << " ";
}
}
outfile << std::endl;
}
}
outfile.close();
}