Commit e2689c1b authored by Andrey Filippov's avatar Andrey Filippov

working on tile processing

parent 21c8e480
......@@ -6,7 +6,7 @@ import ij.IJ;
** GeometryCorrection - geometry correction for multiple sensors sharing the same
** lens radial distortion model
**
** Copyright (C) 2016 Elphel, Inc.
** Copyright (C) 2017 Elphel, Inc.
**
** -----------------------------------------------------------------------------**
**
......@@ -323,6 +323,33 @@ public class GeometryCorrection {
return this.pixelCorrectionHeight * 0.001 * this.pixelSize / this.focalLength;
}
public double getScaleDzDx()
{
return ( 0.001 * this.pixelSize) / this.focalLength;
}
/*
* Get real world coordinates from pixel coordinates and nominal disparity
*/
public double [] getWorldCoordinates(
double px,
double py,
double disparity,
boolean correctDistortions) // correct distortion (will need corrected background too !)
{
double pXcd = px - 0.5 * this.pixelCorrectionWidth;
double pYcd = py - 0.5 * this.pixelCorrectionHeight;
double rD = Math.sqrt(pXcd*pXcd + pYcd*pYcd)*0.001*this.pixelSize; // distorted radius in a virtual center camera
double rND2R = correctDistortions?(getRByRDist(rD/this.distortionRadius, false)): 1.0;
double pXc = pXcd * rND2R; // non-distorted coordinates relative to the (0.5 * this.pixelCorrectionWidth, 0.5 * this.pixelCorrectionHeight)
double pYc = pYcd * rND2R; // in pixels
double z = -SCENE_UNITS_SCALE * this.focalLength * this.disparityRadius / (disparity * 0.001*this.pixelSize); // "+" - near, "-" far
double x = SCENE_UNITS_SCALE * pXc * this.disparityRadius / disparity;
double y = -SCENE_UNITS_SCALE * pYc * this.disparityRadius / disparity;
double [] xyz = {x,y,z};
return xyz;
}
/*
* Calculate pixel coordinates for each of numSensors images, for a given (px,py) of the idealized "center" (still distorted) image
* and generic diparity, measured in pixels
......@@ -343,8 +370,6 @@ public class GeometryCorrection {
double [] a={this.distortionC,this.distortionB,this.distortionA,this.distortionA5,this.distortionA6,this.distortionA7,this.distortionA8};
for (int i = 0; i < numSensors; i++){
// non-distorted XY of the shifted location of the individual sensor
// double pXci = pXc + disparity * this.rXY[i][0]; // in pixels
// double pYci = pYc + disparity * this.rXY[i][1];
double pXci = pXc - disparity * this.rXY[i][0]; // in pixels
double pYci = pYc - disparity * this.rXY[i][1];
// calculate back to distorted
......
......@@ -3558,16 +3558,20 @@ public class QuadCLT {
int tilesX,
int tilesY,
Rectangle bounds){
int width = tileSize*bounds.width + 1;
int height = tileSize*bounds.height + 1;
// int width = tileSize*bounds.width + 1;
// int height = tileSize*bounds.height + 1;
int width = tileSize*bounds.width;
int height = tileSize*bounds.height;
// Adding row/column of all 0, assuming java zeroes arrays
int numSlices = imgData.length;
double [][] rslt = new double [numSlices][width*height];
int offset = (tileSize*bounds.y)*tileSize*tilesX + (tileSize*bounds.x);
// System.out.println("bounds = {.x:"+bounds.x + ", .y=" + bounds.y + ", .width=" + bounds.width + ", .height=" + bounds.height+ ", numSlices="+numSlices);
// System.out.println("offset = " + offset+ " tileSize = "+tileSize);
for (int y = 0; y < (height - 1); y ++){
for (int x = 0; x < width-1; x ++){
// for (int y = 0; y < (height - 1); y ++){
// for (int x = 0; x < width-1; x ++){
for (int y = 0; y < height; y ++){
for (int x = 0; x < width; x ++){
int indx = width * y + x;
int indx_in = indx + offset;
for (int i = 0; i < numSlices; i++) {
......@@ -4732,13 +4736,9 @@ public class QuadCLT {
tp.clt_3d_passes);
x3dOutput.generateBackground();
String path= correctionsParameters.selectX3dDirectory(
String x3d_path= correctionsParameters.selectX3dDirectory(
true, // smart,
true); //newAllowed, // save
if (path != null){
path+=Prefs.getFileSeparator()+name+".x3d";
x3dOutput.generateX3D(path);
}
// testing 2-nd pass
tp.secondPassSetup( // prepare tile tasks for the second pass based on the previous one(s)
......@@ -4751,6 +4751,7 @@ public class QuadCLT {
clt_parameters.bgnd_maybe, // double this_maybe, // maximal strength to ignore as non-background
clt_parameters.sure_smth, // sure_smth, // if 2-nd worst image difference (noise-normalized) exceeds this - do not propagate bgnd
ImageDtt.DISPARITY_INDEX_CM, // index of disparity value in disparity_map == 2 (0,2 or 4)
geometryCorrection,
threadsMax, // maximal number of threads to launch
updateStatus,
debugLevel);
......@@ -4770,12 +4771,13 @@ public class QuadCLT {
}
int scan_limit = 10;
for (int scanIndex = 1; (scanIndex < tp.clt_3d_passes.size()) && (scanIndex < scan_limit); scanIndex++){ // just temporary limiting
// int scan_limit = 10;
for (int scanIndex = 1; (scanIndex < tp.clt_3d_passes.size()) && (scanIndex < clt_parameters.max_clusters); scanIndex++){ // just temporary limiting
if (debugLevel > -1){
System.out.println("Generating cluster images, hardwired limit of "+scan_limit+" largest, scan #"+scanIndex);
System.out.println("Generating cluster images (limit is set to "+clt_parameters.max_clusters+") largest, scan #"+scanIndex);
}
ImagePlus cluster_image = getPassImage( // get image form a single pass
// ImagePlus cluster_image = getPassImage( // get image form a single pass
String texturePath = getPassImage( // get image form a single pass
clt_parameters,
colorProcParameters,
rgbParameters,
......@@ -4784,15 +4786,126 @@ public class QuadCLT {
threadsMax, // maximal number of threads to launch
updateStatus,
debugLevel);
TileProcessor.CLTPass3d scan = tp.clt_3d_passes.get(scanIndex);
// TODO: use new updated disparity, for now just what was forced for the picture
double [] scan_disparity = new double [tp.tilesX * tp.tilesY];
int indx = 0;
for (int ty = 0; ty < tp.tilesY; ty ++) for (int tx = 0; tx < tp.tilesX; tx ++){
scan_disparity[indx++] = scan.disparity[ty][tx];
}
if (clt_parameters.avg_cluster_disp){
double sw = 0.0, sdw = 0.0;
for (int i = 0; i< scan_disparity.length; i++){
if (scan.selected[i] && !scan.border_tiles[i]){
double w = scan.disparity_map[ImageDtt.DISPARITY_STRENGTH_INDEX][i];
sw +=w;
sdw += scan_disparity[i]*w;
}
}
sdw/=sw;
for (int i = 0; i< scan_disparity.length; i++){
scan_disparity[i] = sdw;
}
}
generateClusterX3d(
x3dOutput,
texturePath,
scan.bounds,
scan.selected,
scan_disparity, // scan.disparity_map[ImageDtt.DISPARITY_INDEX_CM],
clt_parameters.transform_size,
clt_parameters.correct_distortions, // requires backdrop image to be corrected also
(scanIndex <2) && clt_parameters.show_triangles,
clt_parameters.bgnd_range,
clt_parameters.other_range,
clt_parameters.maxDispTriangle);
}
// now generate and save texture files (start with full, later use bounding rectangle?)
if (x3d_path != null){
x3d_path+=Prefs.getFileSeparator()+name+".x3d";
x3dOutput.generateX3D(x3d_path);
}
return imp_bgnd; // relative (to x3d directory) path - (String) imp_bgnd.getProperty("name");
}
public void generateClusterX3d(
X3dOutput x3dOutput,
String texturePath,
Rectangle bounds,
boolean [] selected,
double [] disparity,
int tile_size,
boolean correctDistortions, // requires backdrop image to be corrected also
boolean show_triangles,
double min_disparity,
double max_disparity,
double maxDispTriangle
)
{
int [][] indices = tp.getCoordIndices( // starting with 0, -1 - not selected
bounds,
selected);
double [][] texCoord = tp.getTexCoords( // get texture coordinates for indices
indices);
double [][] worldXYZ = tp.getCoords( // get world XYZ in meters for indices
disparity,
min_disparity,
max_disparity,
bounds,
indices,
tile_size,
correctDistortions, // requires backdrop image to be corrected also
this.geometryCorrection);
double [] indexedDisparity = tp.getIndexedDisparities( // get disparity for each index
disparity,
min_disparity,
max_disparity,
bounds,
indices,
tile_size);
int [][] triangles = tp.triangulateCluster(
indices);
triangles = tp.filterTriangles(
triangles,
indexedDisparity, // disparities per vertex index
maxDispTriangle); // maximal disparity difference in a triangle
if (show_triangles) {
tp.testTriangles(
texturePath,
bounds,
selected,
disparity,
tile_size,
indices,
triangles);
}
x3dOutput.addCluster(
texturePath,
texCoord,
worldXYZ,
triangles);
}
public ImagePlus getBackgroundImage(
EyesisCorrectionParameters.CLTParameters clt_parameters,
EyesisCorrectionParameters.ColorProcParameters colorProcParameters,
......@@ -4936,7 +5049,8 @@ public class QuadCLT {
public ImagePlus getPassImage( // get image form a single pass
// public ImagePlus getPassImage( // get image form a single pass
public String getPassImage( // get image form a single pass, return relative path for x3d
EyesisCorrectionParameters.CLTParameters clt_parameters,
EyesisCorrectionParameters.ColorProcParameters colorProcParameters,
EyesisCorrectionParameters.RGBParameters rgbParameters,
......@@ -5011,8 +5125,10 @@ public class QuadCLT {
int width = resize ? (clt_parameters.transform_size * scan.bounds.width + 1): (clt_parameters.transform_size * tp.tilesX);
int height = resize ? (clt_parameters.transform_size * scan.bounds.height + 1): (clt_parameters.transform_size * tp.tilesY);
// int width = resize ? (clt_parameters.transform_size * scan.bounds.width + 1): (clt_parameters.transform_size * tp.tilesX);
// int height = resize ? (clt_parameters.transform_size * scan.bounds.height + 1): (clt_parameters.transform_size * tp.tilesY);
int width = resize ? (clt_parameters.transform_size * scan.bounds.width): (clt_parameters.transform_size * tp.tilesX);
int height = resize ? (clt_parameters.transform_size * scan.bounds.height): (clt_parameters.transform_size * tp.tilesY);
// sdfa_instance = new showDoubleFloatArrays(); // just for debugging?
// sdfa_instance.showArrays(texture_rgbx, width, height, true, "texture_rgbx");
......@@ -5044,7 +5160,7 @@ public class QuadCLT {
correctionsParameters.png,
clt_parameters.show_textures,
-1); // jpegQuality){// <0 - keep current, 0 - force Tiff, >0 use for JPEG
return imp_texture_cluster;
return imp_texture_cluster.getTitle()+".png"; // imp_texture_cluster;
}
......
This source diff could not be displayed because it is too large. You can view the blob instead.
import java.util.ArrayList;
import java.io.File;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
/**
**
......@@ -38,6 +22,23 @@ import org.w3c.dom.Element;
** -----------------------------------------------------------------------------**
**
*/
import java.util.ArrayList;
import java.io.File;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
// Will use 1m units
public class X3dOutput {
......@@ -50,6 +51,7 @@ public class X3dOutput {
Element el_X3d;
Element el_Scene;
Element el_TopGroup;
public int max_line_length = 0; // 100; // 0 - no limit
public X3dOutput(
EyesisCorrectionParameters.CLTParameters clt_parameters,
......@@ -106,6 +108,87 @@ public class X3dOutput {
el_Bgnd.setAttribute("bottomUrl", bgnd_pass.texture);
el_Scene.appendChild(el_Bgnd);
}
public void addCluster(
String url,
double [][] texCoord,
double [][] coordinate,
int [][] triangles)
{
// public int max_line_length = 100; // 0 - no limit
int linepos = 0;
StringBuffer sb_coord_index = new StringBuffer();
for (int i = 0; i < triangles.length; i++){
if ((max_line_length > 0) && ((sb_coord_index.length()-linepos) >= max_line_length)){
sb_coord_index.append("\n");
linepos = 0;
} else if ((linepos > 0) || ((max_line_length == 0) && (sb_coord_index.length() > 0))){
sb_coord_index.append(" ");
}
// sb_coord_index.append(triangles[i][0]+" "+triangles[i][1]+" "+triangles[i][2]+" -1");
sb_coord_index.append(triangles[i][2]+" "+triangles[i][1]+" "+triangles[i][0]+" -1");
}
StringBuffer sb_coords = new StringBuffer();
linepos = 0;
for (int i = 0; i < coordinate.length; i++){
if ((max_line_length >0) && ((sb_coords.length()-linepos) >= max_line_length)){
sb_coords.append("\n");
linepos = 0;
} else if ((linepos > 0) || ((max_line_length == 0) && (sb_coords.length() > 0))){
sb_coords.append(" ");
}
sb_coords.append(String.format("%.3f %.3f %.3f", coordinate[i][0], coordinate[i][1], coordinate[i][2]));
}
StringBuffer sb_tex_coords = new StringBuffer();
linepos = 0;
for (int i = 0; i < texCoord.length; i++){
if ((max_line_length >0) && ((sb_tex_coords.length()-linepos) >= max_line_length)){
sb_tex_coords.append("\n");
linepos = 0;
} else if ((linepos > 0) || ((max_line_length == 0) && (sb_tex_coords.length() > 0))){
sb_tex_coords.append(" ");
}
sb_tex_coords.append(String.format("%.4f %.4f", texCoord[i][0], texCoord[i][1]));
}
String sindex = sb_coord_index.toString(); // for both coordIndex and texCoordIndex
String scoord = sb_coords.toString();
String stcoord = sb_tex_coords.toString();
Element el_shape = x3dDoc.createElement("Shape");
el_Scene.appendChild(el_shape);
Element el_appearance = x3dDoc.createElement("Appearance");
el_shape.appendChild(el_appearance);
Element el_material = x3dDoc.createElement("Material");
el_appearance.appendChild(el_material);
el_material.setAttribute("diffuseColor", "0.376471 0.5 0.376471");
Element el_imageTexture = x3dDoc.createElement("ImageTexture");
el_imageTexture.setAttribute("url",url);
el_appearance.appendChild(el_imageTexture);
Element el_IFC = x3dDoc.createElement("IndexedFaceSet");
el_IFC.setAttribute("coordIndex", sindex); // can it be reused?
el_IFC.setAttribute("texCoordIndex", sindex);
el_shape.appendChild(el_IFC);
Element el_coordinate = x3dDoc.createElement("Coordinate");
el_coordinate.setAttribute("point", scoord);
el_IFC.appendChild(el_coordinate);
Element el_texCoordinate = x3dDoc.createElement("TextureCoordinate");
el_texCoordinate.setAttribute("point", stcoord);
el_IFC.appendChild(el_texCoordinate);
}
// close document, generate x3d file
public void generateX3D(String path)
{
......@@ -130,46 +213,10 @@ public class X3dOutput {
public double [][] getBBox() // center: x,y,z, size:x,y,z
{
double depth = geometry_correction.getZFromDisparity(clt_parameters.bgnd_range);
double depth = geometry_correction.getZFromDisparity(clt_parameters.bgnd_range);
double width = depth * geometry_correction.getFOVWidth();
double height = depth * geometry_correction.getFOVHeight();
double [][] bbox = {{0, 0, depth/2},{width,height,depth}};
double [][] bbox = {{0, 0, -depth/2},{width,height,depth}};
return bbox;
}
}
/*
An IndexedFaceSet geometry node creates geometry out of faces
texCoord and texCoordIndex - specify texture pieces
Shape {
appearance Appearance { . . . }
geometry IndexedFaceSet {
coord Coordinate { . . . }
coordIndex [ . . . ]
texCoord TextureCoordinate { . . . }
texCoordIndex [ . . . ]
}
}
<IndexedFaceSet coordIndex="0 1 2 -1 0 2 3 -1 ..." texCoordIndex="0 1 2 -1 0 2 3 -1 ...">
<Coordinate point="-37.500000 4.000000 -46.450000 .../>
<TextureCoordinate point="-37.500000 4.000000 -46.450000 .../>
</IndexedFaceSet>
<Shape DEF='Back'>
<IndexedFaceSet coordIndex='7 6 5 4' texCoordIndex='0 1 2 3'>
<Coordinate USE='Points'/>
<TextureCoordinate USE='DefaultTextureCoordinate'/>
</IndexedFaceSet>
<Appearance>
<ImageTexture
url=' "images/back.png" "http://x3dGraphics.com/examples/X3dForAdvancedModeling/GeometricShapes/images/back.png" "http://www.web3d.org/x3d/content/examples/Basic/DistributedInteractiveSimulation/images/back.png" '/>
<TextureTransform USE='RotateRight'/>
</Appearance>
</Shape>
*/
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment