Commit 3db21f77 authored by Andrey Filippov's avatar Andrey Filippov

Merge branch 'foliage-gpu' of git.elphel.com:Elphel/imagej-elphel into foliage-gpu

parents 96cca29d 8946631f
......@@ -44,6 +44,7 @@ import ij.process.ImageConverter;
import ij.process.ImageProcessor;
public class CuasMotion {
final public static String CLEAN_SUFFIX = "-CLEAN";
final static public int MAX_ALT_TARGETS = 100; // convenient to be power of 10
final static private int INDX_VX = 0;
......@@ -53,6 +54,13 @@ public class CuasMotion {
final static private int INDX_SPEED = 4; // calculated separately
final static private int INDX_CONFIDENCE = 5; // calculated separately
final static String [] VF_TOP_TITLES = {"vX","vY","strength","fraction","speed", "confidence"};
final static public String LEGEND_TITLE = "Legend";
final static public String[] ICON_DESCRIPTIONS = {
"Identified UAS",
"Unidentified targets",
"UAS flight log position (image pane)",
"UAS flight log position (radar pane)",
"Target detected position (radar pane)"};
final static public int TARGET_X = 0;
final static public int TARGET_Y = 1;
......@@ -97,23 +105,26 @@ public class CuasMotion {
{"diamond21x17.png", "diamond43x35_2px.png"} // foe
};
public static String ICON_BLUE = "Circle63x63blue.png";
public static final String [][] ANNOT_LABELS = {{"Target ID","Unique number fo detected targets, some targets may be erroneously detected as separate ones."},
{"Disparity","Raw measured disparity (in pixels), offset by the same \"disparity at infinity\"."},
{"Range","Distance to the target, calculated from the measured disparity."},
{"True range","Distance to the test UAS obtained from its flight log."},
{"AGL","Altitude above ground level."},
{"Azimuth","Target azimuth (degrees)."},
{"Elevation","Target elevation (degrees)."},
{"Conditional Elevation","Display elevation only if altitude (AGL) is undefined due to too far targets."},
{"Angular movements","Show horizontal and vertical apparent target movement in the camera field of view (degrees per second)."},
{"Vertical Speed","Target vertical speed (m/s)."},
{"Ground Speed","Horizontal target speed relative to the ground (m/s)."},
{"Heading","Target heading (m/s)."},
{"Segment Mismatch","Mismatch between target tracking at consecutive keyframes (now 10 frames @ 60fps) (pix)."},
{"Score","Target 2D detection score."},
{"Sequence Length","Number of consecutive keyframes where the same target is detected."},
{"Travel 2D","Bounding box diagonal of the target 2D travel in consecutive frames (pix)."}};
public static final String OMEGA = "\u03A9";
public static final String [][] ANNOT_LABELS = { // first filed should be 4 character wide
{"ID ", "Target ID", "Unique number of detected targets."}, // , some targets may be erroneously detected as separate ones."},
{"DISP", "Disparity", "Raw measured disparity (in pixels), offset by the same \"disparity at infinity\"."},
{"RNG ", "Range", "Distance to the target, calculated from the measured disparity."},
{"TRNG", "True range","Distance to the test UAS obtained from its flight log."},
{"AGL ", "AGL", "Altitude above ground level."},
{"AZ ", "Azimuth", "Target azimuth (degrees)."},
{"EL ", "Elevation", "Target elevation (degrees)."},
{null, "Conditional Elevation","Display elevation only if altitude (AGL) is undefined due to too far targets."}, // not a label
{OMEGA+"AZ ","Azimuth rotation","Horizontal apparent target movement in the camera field of view (degrees per second)."},
{OMEGA+"EL ","Elevation rotation","Vertical apparent target movement in the camera field of view (degrees per second)."},
{"VS ", "Vertical Speed","Target vertical speed (m/s)."},
{"GS ", "Ground Speed","Horizontal target speed relative to the ground (m/s)."},
{"HDG ","Heading","Target heading (degrees)."},
{"ERRb","Segment Mismatch Before","Mismatch from the previous keyframe (now 10 frames @ 60fps) (pix)."},
{"ERRa","Segment Mismatch After", "Mismatch from the next keyframes (now 10 frames @ 60fps) (pix)."},
{"S ", "Score","Target 2D detection score."},
{"SEQ ", "Sequence Length","Number of consecutive keyframes where the same target is detected."},
{"TRV ", "Travel 2D","Bounding box diagonal of the target 2D travel in consecutive frames (pix)."}};
public static final int ANNOT_ID = 0; // target ID (global index)
public static final int ANNOT_DISP = 1; // disparity
......@@ -123,14 +134,17 @@ public class CuasMotion {
public static final int ANNOT_AZ = 5; // azimuth
public static final int ANNOT_EL = 6; // elevation
public static final int ANNOT_ELNOAGL=7; // elevation if no AGL is available. should be after ANNOT_AGL
public static final int ANNOT_OMEGA = 8; // omega_az,omega_el
public static final int ANNOT_VS = 9; // vertical speed
public static final int ANNOT_GS = 10; // ground speed
public static final int ANNOT_HDG = 11; // heading
public static final int ANNOT_MISM = 12; // Mismatch before/after
public static final int ANNOT_SCORE =13; // Score
public static final int ANNOT_SEQ = 14; // Sequence length
public static final int ANNOT_TRV = 15; // Sequence travel (pixel diagonal of the bounding box of travel)
public static final int ANNOT_OMEGA_AZ = 8; // omega_az
public static final int ANNOT_OMEGA_EL = 9; // omega_el
public static final int ANNOT_VS = 10; // vertical speed
public static final int ANNOT_GS = 11; // ground speed
public static final int ANNOT_HDG = 12; // heading
// public static final int ANNOT_MISM = 13; // Mismatch before/after
public static final int ANNOT_ERRB = 13; // Mismatch before
public static final int ANNOT_ERRA = 14; // Mismatch after
public static final int ANNOT_SCORE =15; // Score
public static final int ANNOT_SEQ = 16; // Sequence length
public static final int ANNOT_TRV = 17; // Sequence travel (pixel diagonal of the bounding box of travel)
/*
public static final int ANNOT_CLEAN =
(1 << ANNOT_ID) |
......@@ -152,16 +166,19 @@ public class CuasMotion {
(1 << ANNOT_AZ) |
(1 << ANNOT_EL) |
(1 << ANNOT_ELNOAGL) |
(1 << ANNOT_OMEGA) |
(1 << ANNOT_OMEGA_AZ) |
(1 << ANNOT_OMEGA_EL) |
(1 << ANNOT_VS) |
(1 << ANNOT_GS) |
(1 << ANNOT_HDG) |
(1 << ANNOT_MISM) |
(1 << ANNOT_ERRB) |
(1 << ANNOT_ERRA) |
(1 << ANNOT_SCORE) |
(1 << ANNOT_SEQ) |
(1 << ANNOT_TRV),
(1 << ANNOT_ID) |
(1 << ANNOT_DISP) |
(1 << ANNOT_RANGE) |
(1 << ANNOT_TRANG) |
(1 << ANNOT_AGL) |
......@@ -169,7 +186,8 @@ public class CuasMotion {
(1 << ANNOT_ELNOAGL) |
(1 << ANNOT_VS) |
(1 << ANNOT_GS) |
(1 << ANNOT_HDG),
(1 << ANNOT_HDG)|
(1 << ANNOT_SCORE),
(1 << ANNOT_ID) |
(1 << ANNOT_RANGE) |
......@@ -3361,7 +3379,7 @@ public class CuasMotion {
/**
* Generate target images
* Generate target images in image pane
* @param clt_parameters
* @param centered target is rendered in the center of the selected tile
* @param mask_width mask width around the target
......@@ -3375,7 +3393,6 @@ public class CuasMotion {
* @param frame_step numer of frames between key frames
* @param velocity_scale velocity scale to apply to vX, vY. It is equal to 1.0/corr_ofset, where corr_offset is disparity in frames
* used for vector field generation
* @param targets60hz target data for each 60hz scene
* @param batch_mode batch mode - disable graphic debugging
* @param debugLevel debug level
* @return float [][] rendered
......@@ -3392,7 +3409,7 @@ public class CuasMotion {
final int frame0,
final int frame_step,
final double velocity_scale, // 1.0/(disparity in frames)
final double [][][] targets60hz,
// final double [][][] targets60hz,
final boolean batch_mode,
final int debugLevel) {
final float [][] fpix_out = new float [background.length][];
......@@ -3519,9 +3536,9 @@ public class CuasMotion {
};
}
ImageDtt.startAndJoin(threads);
if (targets60hz != null) {
targets60hz[nscene] = targets_data;
}
// if (targets60hz != null) {
// targets60hz[nscene] = targets_data;
// }
keyframe = null; // to prevent additional transfers to the GPU
}
}
......@@ -4008,23 +4025,18 @@ public class CuasMotion {
return iclt_fimg[0][0].clone();
}
public ImagePlus convertToRgbAnnotateTargets(
CLTParameters clt_parameters,
final boolean clean_pass,
final double input_range, // 5
final boolean scale2x,
final int target_type, // = 0; // 0 - unknown, 1 - known, 2 - friend, 3 - foe
final int known_type, // 2; // Target location matching UAS flight log: 0; // 0 - unknown, 1 - known, 2 - friend, 3 - foe
final double known_err, // 20; // Maximal distance between the detected target and UAS log position (in raw image pixels);
final float [][] fpixels,
final double [][][] targets60hz,
/// final double [][][] targets60hz,
final boolean change_color,
final boolean show_disp, // true; // Show disparity (corrected) near target (*** not in clean***)
final boolean show_rng, // true; // Show distance to target (range) in meters
final boolean show_inf, // true; // Show distance greater than max (or negativce) as infinity
final boolean show_inf_gt, // false; // Use ">max" instead of infinity symbol
final boolean show_true_rng,// show true range (from the flight log)
final boolean show_mismatch,
final boolean show_score,
final boolean show_uas,
final int frame0,
final int frame_step,
......@@ -4033,10 +4045,21 @@ public class CuasMotion {
final String [] titles,
final UasLogReader uasLogReader,
final int debugLevel) {
final boolean annot_missing = clt_parameters.imp.cuas_annot_missing; // false; // make a parameter.Reserve a line for requested but missing parameters
int annot_mode0 = clt_parameters.imp.cuas_annot_sel[CuasMotion.ANNOT_IMAGE_PANE_INDX];
if (clean_pass) {
annot_mode0 &= clt_parameters.imp.cuas_annot_sel[ANNOT_CLEAN_VIEW_INDX]; //ANNOT_CLEAN;
}
final int annot_mode = annot_mode0;
if (debugLevel > -4) {
System.out.println(String.format("Image annotation mode 0x%04x (0x%04x & 0x%04x)",
annot_mode, clt_parameters.imp.cuas_annot_sel[CuasMotion.ANNOT_RADAR_PANE_INDX],clt_parameters.imp.cuas_annot_sel[ANNOT_CLEAN_VIEW_INDX]));
}
// parentCLT
final GeometryCorrection gc = parentCLT.getGeometryCorrection();
String uas_log_path = null;
// final GeometryCorrection gc = parentCLT.getGeometryCorrection();
// String uas_log_path = null;
boolean annotate_uas = show_uas && (uasLogReader != null);
/*
if (annotate_uas) {
String resource_name = ICON_BLUE;
URL resourceUrl = CuasMotion.class.getClassLoader().getResource("graphics/"+resource_name);
......@@ -4050,64 +4073,29 @@ public class CuasMotion {
uas_log_path = resourcePath.toString();
System.out.println("uas_log_path="+uas_log_path);
}
*/
final double [] camera_atr = uasLogReader.getCameraATR();
final ErsCorrection ersCorrection = parentCLT.getErsCorrection();
// prepare UAS log icon (blue circle)
ColorProcessor uaslog_cp = annotate_uas? getUasLogIconColorProcessor():null;
// preparation of the undetected target icon
String undetected_resource_name = TARGET_ICONS[target_type][scale2x? 1 : 0];
URL undetected_resourceUrl = CuasMotion.class.getClassLoader().getResource("graphics/"+undetected_resource_name);
Path undetected_resourcePath = null;
try {
undetected_resourcePath = Paths.get(undetected_resourceUrl.toURI());
} catch (URISyntaxException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String undetected_path = undetected_resourcePath.toString();
ColorProcessor undetected_cp = null;
try {
undetected_cp = new ColorProcessor(ImageIO.read(new File(undetected_path)));
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
final int undetected_width = undetected_cp.getWidth();
final int undetected_height = undetected_cp.getHeight();
final int [] undetected_pixels = ((int []) undetected_cp.getPixels());
final int [][] undetected_rgba = new int [undetected_pixels.length][4];
for (int i = 0; i < undetected_rgba.length; i++) {
for (int s = 0; s <4; s++) {
undetected_rgba[i][s] = (undetected_pixels[i] >> (8 * s)) & 0xff;
}
}
// preparation of the detected target icon
String detected_resource_name = TARGET_ICONS[known_type][scale2x? 1 : 0];
URL detected_resourceUrl = CuasMotion.class.getClassLoader().getResource("graphics/"+detected_resource_name);
Path detected_resourcePath = null;
try {
detected_resourcePath = Paths.get(detected_resourceUrl.toURI());
} catch (URISyntaxException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String detected_path = detected_resourcePath.toString();
ColorProcessor detected_cp = null;
try {
detected_cp = new ColorProcessor(ImageIO.read(new File(detected_path)));
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
final int detected_width = detected_cp.getWidth();
final int detected_height = detected_cp.getHeight();
// prepare target icons
ColorProcessor cp_target_icon = getIconColorProcessor(
target_type, // int target_type, // Target location matching UAS flight log: 0; // 0 - unknown, 1 - known, 2 - friend, 3 - foe
scale2x); // boolean scale2x)
ColorProcessor cp_uas_icon = getIconColorProcessor(
known_type, // uas_type, // int target_type, // Target location matching UAS flight log: 0; // 0 - unknown, 1 - known, 2 - friend, 3 - foe
scale2x); // boolean scale2x)
final int uaslog_width = (uaslog_cp != null) ? uaslog_cp.getWidth() : 0;
final int target_icon_width = cp_target_icon.getWidth();
final int uas_icon_width = cp_uas_icon.getWidth();
final int [] uaslog_pixels = (int[]) uaslog_cp.getPixels();
final int [] target_icon_pixels = (int[]) cp_target_icon.getPixels();
final int [] uas_icon_pixels = (int[]) cp_uas_icon.getPixels();
final int [][] uaslog_rgba = splitColorIcon(uaslog_pixels);
final int [][] target_icon_rgba = splitColorIcon(target_icon_pixels);
final int [][] uas_icon_rgba = splitColorIcon(uas_icon_pixels);
final int [] detected_pixels = ((int []) detected_cp.getPixels());
final int [][] detected_rgba = new int [detected_pixels.length][4];
for (int i = 0; i < detected_rgba.length; i++) {
for (int s = 0; s <4; s++) {
detected_rgba[i][s] = (detected_pixels[i] >> (8 * s)) & 0xff;
}
}
final int scale = scale2x? 2 : 1;
final Thread[] threads = ImageDtt.newThreadArray(QuadCLT.THREADS_MAX);
final AtomicInteger ai = new AtomicInteger(0);
......@@ -4127,40 +4115,12 @@ public class CuasMotion {
final String font_name = clt_parameters.imp.cuas_font_name;
final int font_size = clt_parameters.imp.cuas_font_size;
final int font_type = clt_parameters.imp.cuas_font_type;
final int space_before_text = 2;
final double rng_limit = clt_parameters.imp.cuas_rng_limit;
ColorProcessor uaslog_cp = null;
if (uas_log_path != null) {
try {
uaslog_cp = new ColorProcessor(ImageIO.read(new File(uas_log_path)));
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
final int uaslog_width = (uaslog_cp != null) ? uaslog_cp.getWidth() : 0;
final int uaslog_height = (uaslog_cp != null) ? uaslog_cp.getHeight() : 0;
final int [] uaslog_pixels = (uaslog_cp != null) ? ((int []) uaslog_cp.getPixels()) : null;
final int [][] uaslog_rgba = (uaslog_cp != null) ? (new int [uaslog_pixels.length][4]) : null;
if (uaslog_cp != null) {
for (int i = 0; i < uaslog_rgba.length; i++) {
for (int s = 0; s <4; s++) {
uaslog_rgba[i][s] = (uaslog_pixels[i] >> (8 * s)) & 0xff;
}
}
}
if (uaslog_pixels != null) {
System.out.println("uaslog_width="+uaslog_width+",uaslog_height="+uaslog_height);
}
final int space_before_text = 2 * scale;
final double font_ratio = clt_parameters.imp.cuas_font_spacing; // 1.2; // if 0 - will use default spacing ( ~=1.5)
final int tileSize = GPUTileProcessor.DTT_SIZE;
final int num_scenes = fpixels.length;
final int num_pixels = fpixels[0].length;
final int num_seq = targets60hz.length;
// final int height = num_pixels/width;
final int num_seq = targets.length;
ImagePlus imp = ShowDoubleFloatArrays.makeArrays(
fpixels, // float[][] pixels,
width_src, // int width,
......@@ -4225,19 +4185,14 @@ public class CuasMotion {
color_stack.addSlice(cp_labels[i],color_processors[i]);
}
imp = new ImagePlus(imp_title, color_stack); // imp.getTitle(),stack);
final int width = imp.getProcessor().getWidth();
final int height = imp.getProcessor().getHeight();
// imp.show();
final Color fcolor = annotate_color_mono;
final ImageStack fstack_scenes = imp.getImageStack();
final int posX= width - scale * 119; // 521;
final int posY= height + scale * 1; // 513;
final Font font = new Font("Monospaced", Font.PLAIN, scale * 12);
final Font font_target = new Font(font_name, font_type, scale * font_size);
// final boolean target_text_transparent = true;
final int nSlices = fstack_scenes.getSize();
if (annotate_mono) {
ai.set(0);
......@@ -4265,163 +4220,263 @@ public class CuasMotion {
for (int i = 0; i < num_scenes; i++) {
ipixels[i] = (int[]) stack.getPixels(i+1);
}
// final int num_seq = targets60hz.length;
final int half_step0 = -(frame_step+1)/2;
final int half_step1 = frame_step + half_step0;
ai.set(0);
final AtomicInteger amax = new AtomicInteger(-1);
final int [] uas_tiles = new int[num_seq];
Arrays.fill(uas_tiles, -1);
final int [][] local_tiles = new int [num_seq][];
final int num_tiles = targets[0].length; // java.lang.NullPointerException
for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() {
public void run() {
for (int nSeq = ai.getAndIncrement(); nSeq < num_seq; nSeq = ai.getAndIncrement()) {
int frame_center = frame0 + nSeq * frame_step;
for (int dscene = half_step0; dscene < half_step1; dscene ++) {
int nscene = frame_center + dscene;
if ((nscene >=0) && (nscene < num_scenes)) {
double [] uas_pXpYDRange = uasLogReader.getUasPxPyDRange(titles[nscene]);
if (uaslog_rgba != null) { // draw uas from log
// get drone pixel coordinates
int xc = (int) Math.round(scale * uas_pXpYDRange[0]);
int yc = (int) Math.round(scale * uas_pXpYDRange[1]);
int xl = xc - uaslog_width/2;
int yt = yc - uaslog_height/2;
if (nSeq < 0) { // disabled debug, keep 3 to use // 3) {
System.out.println(String.format("uas_pXpYD=[%f,%f,%f]",uas_pXpYDRange[0],uas_pXpYDRange[1],uas_pXpYDRange[2]));
System.out.println(String.format("xc=%d, yc=%d, xl=%d, yt=%d",xc,yc,xl,yt));
System.out.println(String.format("A=%f, T=%f, R=%f",uasLogReader.getCameraATR()[0],uasLogReader.getCameraATR()[1],uasLogReader.getCameraATR()[1]));
System.out.println(String.format("titles[nscene]=%s, startTimeStamp=%f",titles[nscene],uasLogReader.getStartTimestamp()));
}
for (int y = 0; y < uaslog_height; y++) {
int py = yt + y;
if ((py >= 0) && (py < height)) {
for (int x = 0; x< uaslog_width; x++) {
int px = xl +x;
int dpix = x + y * uaslog_width;
int ipix = px + py*width;
if ((px >=0) && (px < width)) {
int alpha = uaslog_rgba[dpix][3];
if (alpha > 0) { // alpha
int dp = uaslog_pixels[x + y * uaslog_width];
if (alpha == 255) {
ipixels[nscene][ipix] = dp;
} else {
double k = alpha/255.0;
int img_pix = ipixels[nscene][ipix];
int new_pix = 0xff000000;
for (int c = 0; c < 3; c++) {
int rgb = (img_pix >> (8 * c)) & 0xff;
rgb = (int) Math.round((1-k)*rgb + k* uaslog_rgba[dpix][c]);
if (rgb > 255) rgb = 255;
new_pix |= (rgb << (8*c));
for (int nSeq = ai.getAndIncrement(); nSeq < targets.length; nSeq = ai.getAndIncrement()) {
double [][] targets_seq = targets[nSeq];
/// key - local target_id > 0
/// Key 0 - special case: tiles where UAS log data is stored (may be the same or different than detected tiles
/// value - tile index
HashMap<Integer,Integer> local_tiles_map = new HashMap<Integer,Integer>(); //
int max_ltarg = -1;
for (int ntile = 0; ntile < num_tiles; ntile++) {
double [] target = targets_seq[ntile];
if (target != null) {
if (!Double.isNaN(target[CuasMotionLMA.RSLT_FL_PX])) {
local_tiles_map.put(0, ntile); // flight log data
max_ltarg = Math.max(max_ltarg, 0);
}
ipixels[nscene][ipix] = new_pix;
if (!Double.isNaN(target[CuasMotionLMA.RSLT_GLOBAL])) {
int ltarg = (int) target[CuasMotionLMA.RSLT_GLOBAL];
max_ltarg = Math.max(max_ltarg, ltarg);
local_tiles_map.put(ltarg, ntile); // target data
}
}
}
amax.getAndAccumulate(max_ltarg, Math::max);
local_tiles[nSeq] = new int[max_ltarg+1];
Arrays.fill(local_tiles[nSeq],-1);
for (int i = 0; i <= max_ltarg; i++) if (local_tiles_map.containsKey(i)) {
local_tiles[nSeq][i] = local_tiles_map.get(i);
}
}
}
};
}
ImageDtt.startAndJoin(threads);
double [][] targets = targets60hz[nscene];
if (targets != null) { // TODO: find why
int matching_target = findMatchingTarget(
targets, // double [][] targets,
uas_pXpYDRange, // double [] uas_pXpYD,
known_err); // double max_dist)
for (int ntarget = 0; ntarget < targets.length; ntarget++) {
int xc = (int) Math.round(scale * targets[ntarget][TARGET_X]);
int yc = (int) Math.round(scale * targets[ntarget][TARGET_Y]);
int icon_width = (ntarget == matching_target) ? detected_width : undetected_width;
int icon_height = (ntarget == matching_target) ? detected_height : undetected_height;
int [][] target_rgba = (ntarget == matching_target) ? detected_rgba : undetected_rgba;
final int [] target_pixels = (ntarget == matching_target) ? detected_pixels : undetected_pixels;
int xl = xc - icon_width/2;
int yt = yc - icon_height/2;
for (int y = 0; y < icon_height; y++) {
int py = yt + y;
if ((py >= 0) && (py < height)) {
for (int x = 0; x< icon_width; x++) {
int px = xl +x;
int dpix = x + y * icon_width;
int ipix = px + py*width;
if ((px >=0) && (px < width)) {
int alpha = target_rgba[dpix][3];
if (alpha > 0) { // alpha
int dp = target_pixels[x + y * icon_width];
if (alpha == 255) {
ipixels[nscene][ipix] = dp;
} else {
double k = alpha/255.0;
int img_pix = ipixels[nscene][ipix];
int new_pix = 0xff000000;
for (int c = 0; c < 3; c++) {
int rgb = (img_pix >> (8 * c)) & 0xff;
rgb = (int) Math.round((1-k)*rgb + k* target_rgba[dpix][c]);
if (rgb > 255) rgb = 255;
new_pix |= (rgb << (8*c));
final int [][] ltargets_first_last = new int [amax.get()][]; // correct
for (int nseq = 0; nseq < num_seq; nseq++) if ((local_tiles[nseq] != null) && (local_tiles[nseq].length > 0)){ // no if is not needed - bug fixed
uas_tiles[nseq] = local_tiles[nseq][0];
}
ipixels[nscene][ipix] = new_pix;
for (int ltarg = 1; ltarg <= ltargets_first_last.length; ltarg++) { // 0 - for UAS log
int indx_first, indx_last;
for (indx_first = 0; (indx_first < num_seq) && ((local_tiles[indx_first].length <= ltarg ) || (local_tiles[indx_first][ltarg] < 0)); indx_first++);
if (indx_first < num_seq) {
for (indx_last = num_seq - 1; (indx_last >= 0) && ((local_tiles[indx_last].length <= ltarg ) || (local_tiles[indx_last][ltarg] < 0)); indx_last--); // Index 5 out of bounds for length 5
ltargets_first_last[ltarg-1] = new int[] {indx_first,indx_last};
}
}
for (int nscene = 0; nscene < num_scenes; nscene++) {
color_processors[nscene].setFont(font_target); // to calculate text boxes, later will need to set it for all processors
}
ai.set(0);
int [] scene_indices = getSceneIndices(
slice_titles, // String [] key_titles, // corresponding to top targets dimension
scene_titles); // String [] scene_titles) { // all titles, one per frame
final Rectangle full_wnd = new Rectangle(0,0,width,height);
ai.set(0);
for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() {
public void run() {
int [] conflict_pix = new int [width * height];
ColorProcessor conflict_cp = new ColorProcessor(width, height, conflict_pix);
for (int nSeq = ai.getAndIncrement(); nSeq < (targets.length - 1); nSeq = ai.getAndIncrement()) {
Arrays.fill(conflict_pix, 0);
// for now only for targets longer that 1 series
int nscene0 = scene_indices[nSeq];
int nscene1 = scene_indices[nSeq+1];
double kscene = 1.0/(nscene1-nscene0);
// plot UAS
double [] uas_target0= null, uas_target1=null;
if ((uas_tiles[nSeq] >= 0) && (uas_tiles[nSeq+1] >= 0)) {
uas_target0= targets[nSeq][uas_tiles[nSeq]];
uas_target1= targets[nSeq+1][uas_tiles[nSeq+1]];
for (int nscene = nscene0; nscene < nscene1; nscene++) { // threads collide if <=
double uk = (nscene - nscene0) * kscene; // 0 when nscene=nscene0
double upx = interpolate(uas_target0[CuasMotionLMA.RSLT_FL_PX], uas_target1[CuasMotionLMA.RSLT_FL_PX], uk);
double upy = interpolate(uas_target0[CuasMotionLMA.RSLT_FL_PY], uas_target1[CuasMotionLMA.RSLT_FL_PY], uk);
int xc = (int) Math.round(scale * upx);
int yc = (int) Math.round(scale * upy);
imprintPixelIcon(
uaslog_rgba, // int [][] icon, // {R,G,B,A}
uaslog_pixels, // int [] icon_pix,
uaslog_width, // int icon_width,
ipixels[nscene], // int [] image,
width, // int width,
xc, // int xc,
yc); // int yc) {
}
}
}
if (annotate) { // TODO: use the same as in radar mode?
int text_left = xl + icon_width + space_before_text * scale;
int text_top = yt + scale * font_size; // text start from the bottom of the first line
ImageProcessor ip = fstack_scenes.getProcessor(nscene+1);
String txt = getTargetText(
clt_parameters, // CLTParameters clt_parameters,
gc, //GeometryCorrection gc,
targets[ntarget]); // double [] target);
if (show_disp) {
double disparity = targets[ntarget][TARGET_DISPARITY];
txt += String.format("\nDISP%4.0f",disparity*1000); // avoid decimal point, show 1000 x disparity
}
double range = targets[ntarget][TARGET_RANGE];
if (show_rng && !Double.isNaN(range) && (range != 0.0)) { // NaN - undefined, 0.0 - undefined
if (show_inf || !Double.isInfinite(range)) {
if (Double.isInfinite(range)) {
if (show_inf_gt) {
txt += String.format("\nRNG>%4.0f",rng_limit);
} else {
txt += "\nRNG \u221E";
}
};
}
ImageDtt.startAndJoin(threads);
} else {
txt += String.format("\nRNG %4.0f",range);
ai.set(0);
for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() {
public void run() {
int [] conflict_pix = new int [width * height];
/// ColorProcessor conflict_cp = new ColorProcessor(width, height, conflict_pix);
for (int nSeq = ai.getAndIncrement(); nSeq < (num_seq - 1); nSeq = ai.getAndIncrement()) {
/// int frame_center = frame0 + nSeq * frame_step;
Arrays.fill(conflict_pix, 0);
// for now only for targets longer that 1 series
int nscene0 = scene_indices[nSeq];
int nscene1 = scene_indices[nSeq+1];
double kscene = 1.0/(nscene1-nscene0);
// int get number of visible targets for this scene sequence
int num_visible = 0;
int [] target_ids = new int [local_tiles[nSeq].length]; // ltargets_first_last.length];
for (int i = 1; i < local_tiles[nSeq].length; i++) {
if ((local_tiles[nSeq][i] > 0) && (i < local_tiles[nSeq + 1].length) && (local_tiles[nSeq + 1][i] > 0)) { // visible in both this and next
num_visible++;
int ntile = local_tiles[nSeq][i]; // 1- based 0 - uas log
double [] target = targets[nSeq][ntile];
target_ids[i] = (int) target[CuasMotionLMA.RSLT_TARGET_ID]; // i was out of range
}
}
Integer [] targets_order_integer = new Integer [num_visible];
int indx = 0;
for (int i = 1; i < local_tiles[nSeq].length; i++) {
if ((local_tiles[nSeq][i] > 0) && (i < local_tiles[nSeq + 1].length) && (local_tiles[nSeq + 1][i] > 0)) { // visible in both this and next
targets_order_integer[indx++] = i;
}
}
Arrays.sort(targets_order_integer, new Comparator<Integer>() { //
@Override
public int compare(Integer lhs, Integer rhs) {
return Integer.compare(target_ids[lhs], target_ids[rhs]);
}
});
// 0-based indices, 0-based values.
final int [] targets_order = Arrays.stream(targets_order_integer).mapToInt(Integer::intValue).toArray();
// double [][] targets = targets60hz[nscene];
if (show_true_rng && (ntarget == matching_target)) {
// uas_pXpYDRange[3]
txt += String.format("\nTRNG%4.0f",uas_pXpYDRange[3]);
// plot targets
// now target_coord is ordered from highest priority to the lowest
double [][][] target_coord = new double [local_tiles[nSeq].length-1][][]; // save centers of targets and text coordinates
Rectangle [][] annot_boxes = new Rectangle[local_tiles[nSeq].length-1][]; // order will match target_coord order
String [][] annots = new String [local_tiles[nSeq].length-1][];
double [] uas_target0= null, uas_target1=null;
if ((uas_tiles[nSeq] >= 0) && (uas_tiles[nSeq+1] >= 0)) {
uas_target0= targets[nSeq][uas_tiles[nSeq]];
uas_target1= targets[nSeq+1][uas_tiles[nSeq+1]];
}
if (show_mismatch) {
txt += String.format("\nErr %3.1f\nErr %3.1f",
targets[ntarget][TARGET_MISMATCH_BEFORE],targets[ntarget][TARGET_MISMATCH_AFTER]);
// prepare and save annotations to later make then non-conficting
for (int iltarget = 0; iltarget < targets_order.length; iltarget ++) {
int ltarget = targets_order[iltarget]; // + 1;
if ( (local_tiles[nSeq].length > ltarget) &&
(local_tiles[nSeq+1].length > ltarget) &&
(local_tiles[nSeq][ltarget] >=0) &&
(local_tiles[nSeq+1][ltarget]>=0)) {
int ntile0 = local_tiles[nSeq ][ltarget];
int ntile1 = local_tiles[nSeq+1][ltarget];
double [] target0= targets[nSeq ][ntile0];
double [] target1= targets[nSeq+1][ntile1];
double px0 = (ntile0 % tilesX +0.5) * tileSize + target0[CuasMotionLMA.RSLT_X]; // ignoring velocities
double py0 = (ntile0 / tilesX +0.5) * tileSize + target0[CuasMotionLMA.RSLT_Y];
double px1 = (ntile1 % tilesX +0.5) * tileSize + target1[CuasMotionLMA.RSLT_X];
double py1 = (ntile1 / tilesX +0.5) * tileSize + target1[CuasMotionLMA.RSLT_Y];
target_coord[iltarget] = new double [nscene1-nscene0+1][4];
annot_boxes[iltarget] = new Rectangle[nscene1-nscene0+1];
annots[iltarget] = new String[nscene1-nscene0+1];
int target_id = target_ids[targets_order[iltarget]];
boolean is_uas = target_id == CuasMultiSeries.TARGET_INDEX_UAS;
int icon_width = is_uas ? uas_icon_width: target_icon_width;
for (int nscene = nscene0; nscene < nscene1; nscene++) { // threads collide if <= (when drawing, here just not needed)
double k = (nscene - nscene0) * kscene; // 0 when nscene=nscene0
double px = scale * interpolate(px0, px1, k);
double py = scale * interpolate(py0, py1, k);
String annot_txt = getAnnotationText(
clt_parameters, // CLTParameters clt_parameters,
annot_mode, // int annot_mode,
annot_missing, // boolean reserve_missing_fields, // make a parameter.Reserve a line for requested but missing parameters
ntile0, // int ntile0,
ntile1, // int ntile1,
target0, // double [] target0,
target1, // double [] target1,
uas_target0, // double [] uas_target0,
uas_target1, // double [] uas_target1,
k, // double k,
camera_atr, // double [] camera_atr,
ersCorrection, // ErsCorrection ersCorrection)
Double.NaN); // double fps); // if NaN, will use default 60Hz. Used only for omegas
target_coord[iltarget][nscene-nscene0][0] = px; // null pointer
target_coord[iltarget][nscene-nscene0][1] = py;
Rectangle text_box = getStringBounds(color_processors[nscene], annot_txt, font_ratio);
// Rectangle abs_box = annot_boxes[iltarget][nscene-nscene0];
double text_left =px + icon_width/2 + space_before_text;
double text_top = py;
target_coord[iltarget][nscene-nscene0][2] = text_left;
target_coord[iltarget][nscene-nscene0][3] = text_top;
annots[iltarget][nscene-nscene0] = annot_txt;
annot_boxes[iltarget][nscene-nscene0] = text_box;
}
if (show_score) {
txt += String.format("\nSEQ %3.1f\nTRV %4.1f\n%5.3f",
targets[ntarget][TARGET_SEQLEN],targets[ntarget][TARGET_TRAVEL], targets[ntarget][TARGET_SCORE]);
}
boolean sel_target = (ntarget == matching_target) && change_color;
ip.setColor(sel_target ? selected_color: text_color);
ip.setFont(font_target);
boolean target_text_transparent = (ntarget == matching_target) ? transparent_uas : transparent_other;
if (target_text_transparent) {
ip.drawString(txt, text_left, text_top); // transparent.
} else {
ip.drawString(txt, text_left, text_top, text_bg_color); // solid color
}
// print annotations
for (int iltarget = targets_order.length - 1; iltarget >=0; iltarget --) {
int target_id = target_ids[targets_order[iltarget]];
boolean is_uas = target_id == CuasMultiSeries.TARGET_INDEX_UAS;
boolean target_text_transparent = is_uas ? transparent_uas : transparent_other;
/// int icon_width = is_uas ? uas_icon_width: target_icon_width;
for (int nscene = nscene0; nscene < nscene1; nscene++) { // threads collide if <=
color_processors[nscene].setColor(is_uas ? selected_color: text_color);
String annot_txt=annots[iltarget][nscene-nscene0];
int text_left = (int)Math.round(target_coord[iltarget][nscene-nscene0][2]);
int text_top = (int)Math.round(target_coord[iltarget][nscene-nscene0][3]);
Rectangle abs_box = annot_boxes[iltarget][nscene-nscene0];
abs_box.x += text_left;
abs_box.y += text_top;
if (full_wnd.contains(abs_box) ) {
Color bg_color = target_text_transparent ? null : text_bg_color; // Color.BLACK;
drawString(
color_processors[nscene], // ImageProcessor ip,
annot_txt, // String txt,
text_left, // int left,
text_top, // int top,
bg_color, // Color bgColor, // null - transparent
font_ratio); // double ratio) { // NaN or 0 - standard
}
}
}
// plot icons
for (int iltarget = 0; iltarget < targets_order.length; iltarget ++) {
int target_id = target_ids[targets_order[iltarget]];
boolean is_uas = target_id == CuasMultiSeries.TARGET_INDEX_UAS;
int [] icon_pixels = is_uas ? uas_icon_pixels : target_icon_pixels;
int [][] icon_rgba = is_uas ? uas_icon_rgba : target_icon_rgba;
int icon_width = is_uas ? uas_icon_width: target_icon_width;
for (int nscene = nscene0; nscene < nscene1; nscene++) {
int ixc= (int) Math.round(target_coord[iltarget][nscene-nscene0][0]);
int iyc= (int) Math.round(target_coord[iltarget][nscene-nscene0][1]);
imprintPixelIcon(
icon_rgba, // int [][] icon,
icon_pixels, // int [] icon_pix,
icon_width, // int icon_width,
ipixels[nscene], // int [] image,
width, // int width,
ixc, // int xc,
iyc); // int yc)
}
}
}
......@@ -4432,6 +4487,11 @@ public class CuasMotion {
return imp;
}
public static ColorProcessor getIconColorProcessor(
int target_type, // Target location matching UAS flight log: 0; // 0 - unknown, 1 - known, 2 - friend, 3 - foe
boolean scale2x) {
......@@ -4455,6 +4515,31 @@ public class CuasMotion {
return cp;
}
public static ColorProcessor getUasLogIconColorProcessor() {
String resource_name = ICON_BLUE;
URL resourceUrl = CuasMotion.class.getClassLoader().getResource("graphics/"+resource_name);
Path resourcePath = null;
try {
resourcePath = Paths.get(resourceUrl.toURI());
} catch (URISyntaxException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String uas_log_path = resourcePath.toString();
/// System.out.println("uas_log_path="+uas_log_path);
ColorProcessor cp = null;
try {
cp = new ColorProcessor(ImageIO.read(new File(uas_log_path)));
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
return cp;
}
public static int [][] splitColorIcon(int [] icon){
final int [][] icon_rgba = new int [icon.length][4];
for (int i = 0; i < icon_rgba.length; i++) {
......@@ -4466,7 +4551,7 @@ public class CuasMotion {
}
public static void imprintPixelIcon(
int [][] icon,
int [][] icon, // {R,G,B,A}
int [] icon_pix,
int icon_width,
int [] image,
......@@ -4566,7 +4651,7 @@ public class CuasMotion {
final double radar_range = clt_parameters.imp.cuas_radar_range;
final String font_name = clt_parameters.imp.cuas_font_name;
final int font_size_radar = clt_parameters.imp.cuas_font_size; // 7; //
final double font_ratio_radar = 1.2; // if 0 - will use default spacing ( ~=1.5)
final double font_ratio_radar = clt_parameters.imp.cuas_font_spacing; // 1.2; // if 0 - will use default spacing ( ~=1.5)
final int font_type = clt_parameters.imp.cuas_font_type;
final Color text_color = clt_parameters.imp.cuas_text_color;
final Color selected_color = text_color; // clt_parameters.imp.cuas_selected_color;
......@@ -5058,7 +5143,7 @@ public class CuasMotion {
String number_frac_format = "%4.1f";
String number_signed_format = "%3.0f";
String omega_format = "%3.1f";
String omega = "\u03A9";
String sinfinity = "\u221E";
boolean show_inf = clt_parameters.imp.cuas_show_inf; // true; // Show distance greater than max (or negativce) as infinity
boolean show_inf_gt = clt_parameters.imp.cuas_show_inf_gt; // false; // Use ">max" instead of infinity symbol
......@@ -5131,6 +5216,8 @@ public class CuasMotion {
double omega_az_degs = omega_az * 180/Math.PI;
double omega_el_degs = omega_el * 180/Math.PI;
double vel_away = interpolate (target0[CuasMotionLMA.RSLT_VEL_AWAY], target1[CuasMotionLMA.RSLT_VEL_AWAY], k);
if (range > max_axial_range) {
vel_away = 0;
......@@ -5147,24 +5234,30 @@ public class CuasMotion {
StringBuffer sb = new StringBuffer();
if ((annot_mode & (1 << ANNOT_ID)) != 0){
sb.append("ID "+String.format(number_unsigned_format,did)+"\n");
// sb.append("ID "+String.format(number_unsigned_format,did)+"\n");
sb.append(ANNOT_LABELS[ANNOT_ID][0]+String.format(number_unsigned_format,did)+"\n");
}
if ((annot_mode & (1 << ANNOT_DISP)) != 0){
if (!Double.isNaN(disparity)) {
sb.append("DISP"+String.format(number_unsigned_format,disparity*1000)+"\n");
// sb.append("DISP"+String.format(number_unsigned_format,disparity*1000)+"\n");
sb.append(ANNOT_LABELS[ANNOT_DISP][0]+String.format(number_unsigned_format,disparity*1000)+"\n");
} else if (reserve_missing_fields){
sb.append("\n");
}
}
if ((annot_mode & (1 << ANNOT_RANGE)) != 0){
String srng = ANNOT_LABELS[ANNOT_RANGE][0];
if (range <= max_annot_range) { // handles POSITIVE_INFINITY
sb.append("RNG "+String.format(number_unsigned_format,range)+"\n");
sb.append(srng+String.format(number_unsigned_format,range)+"\n");
} else if (show_inf && !Double.isNaN(range)){
if (show_inf_gt) {
sb.append("RNG>"+String.format(number_unsigned_format,max_annot_range)+"\n");
srng = srng.substring(0,3)+">";
// sb.append("RNG>"+String.format(number_unsigned_format,max_annot_range)+"\n");
sb.append(srng+String.format(number_unsigned_format,max_annot_range)+"\n");
} else {
sb.append("RNG "+sinfinity+"\n");
// sb.append("RNG "+sinfinity+"\n");
sb.append(srng+sinfinity+"\n");
}
} else if (reserve_missing_fields){
sb.append("\n");
......@@ -5172,7 +5265,8 @@ public class CuasMotion {
}
if ((annot_mode & (1 << ANNOT_TRANG)) != 0){
if (!Double.isNaN(true_range)) {
sb.append("TRNG"+String.format(number_unsigned_format,true_range)+"\n");
// sb.append("TRNG"+String.format(number_unsigned_format,true_range)+"\n");
sb.append(ANNOT_LABELS[ANNOT_TRANG][0]+String.format(number_unsigned_format,true_range)+"\n");
} else if (reserve_missing_fields){
sb.append("\n");
}
......@@ -5180,7 +5274,8 @@ public class CuasMotion {
boolean has_agl = false;
if ((annot_mode & (1 << ANNOT_AGL)) != 0){
if (!Double.isNaN(agl) && (range <= max_annot_range)) {
sb.append("AGL "+String.format(number_unsigned_format,agl)+"\n");
// sb.append("AGL "+String.format(number_unsigned_format,agl)+"\n");
sb.append(ANNOT_LABELS[ANNOT_AGL][0]+String.format(number_unsigned_format,agl)+"\n");
has_agl = true;
} else if (reserve_missing_fields){
sb.append("\n");
......@@ -5188,73 +5283,130 @@ public class CuasMotion {
}
if ((annot_mode & (1 << ANNOT_AZ)) != 0){
if (!Double.isNaN(az_deg)) {
sb.append("AZM "+String.format(number_unsigned_format,az_deg)+"\n");
// sb.append("AZM "+String.format(number_unsigned_format,az_deg)+"\n");
sb.append(ANNOT_LABELS[ANNOT_AZ][0]+String.format(number_unsigned_format,az_deg)+"\n");
} else if (reserve_missing_fields){
sb.append("\n");
}
}
if (((annot_mode & (1 << ANNOT_EL)) != 0) || (!has_agl && ((annot_mode & (1 << ANNOT_ELNOAGL)) != 0)) ){
if (!Double.isNaN(el_deg)) {
// sb.append("EL "+getSignedDouble(el_deg,omega_format)+"\n");
sb.append("EL "+String.format(number_unsigned_format,el_deg)+"\n");
// sb.append("EL "+String.format(number_unsigned_format,el_deg)+"\n");
sb.append(ANNOT_LABELS[ANNOT_EL][0]+String.format(number_unsigned_format,el_deg)+"\n");
} else if (reserve_missing_fields){
sb.append("\n");
}
}
if ((annot_mode & (1 << ANNOT_OMEGA)) != 0){
sb.append(omega+"AZ "+getSignedDouble(omega_az_degs,omega_format)+"\n");
sb.append(omega+"EL "+getSignedDouble(omega_el_degs,omega_format)+"\n");
if ((annot_mode & (1 << ANNOT_OMEGA_AZ)) != 0){
// sb.append(OMEGA+"AZ "+getSignedDouble(omega_az_degs,omega_format)+"\n");
sb.append(ANNOT_LABELS[ANNOT_OMEGA_AZ][0]+getSignedDouble(omega_az_degs,omega_format)+"\n");
}
if ((annot_mode & (1 << ANNOT_OMEGA_EL)) != 0){
// sb.append(OMEGA+"EL "+getSignedDouble(omega_el_degs,omega_format)+"\n");
sb.append(ANNOT_LABELS[ANNOT_OMEGA_EL][0]+getSignedDouble(omega_el_degs,omega_format)+"\n");
}
if ((annot_mode & (1 << ANNOT_VS)) != 0){
if (!Double.isNaN(vel_up) && (range <= max_annot_range)) {
sb.append("VS "+getSignedDouble(vel_up,omega_format)+"\n");
// sb.append("VS "+getSignedDouble(vel_up,omega_format)+"\n");
sb.append(ANNOT_LABELS[ANNOT_VS][0]+getSignedDouble(vel_up,omega_format)+"\n");
} else if (reserve_missing_fields){
sb.append("\n");
}
}
if ((annot_mode & (1 << ANNOT_GS)) != 0){
if (!Double.isNaN(vel_hor) && (range <= max_annot_range)) {
sb.append("GS "+String.format(number_frac_format,vel_hor)+"\n");
// sb.append(String.format("GS %4.1f\n", vel_hor));
// sb.append("GS "+String.format(number_frac_format,vel_hor)+"\n");
sb.append(ANNOT_LABELS[ANNOT_GS][0]+String.format(number_frac_format,vel_hor)+"\n");
} else if (reserve_missing_fields){
sb.append("\n");
}
}
if ((annot_mode & (1 << ANNOT_HDG)) != 0){
if (!Double.isNaN(hdg_deg) && (range <= max_annot_range)) {
sb.append("HDG "+String.format(number_unsigned_format,hdg_deg)+"\n");
// sb.append(String.format("HDG %4.0f\n", hdg_deg));
// sb.append("HDG "+String.format(number_unsigned_format,hdg_deg)+"\n");
sb.append(ANNOT_LABELS[ANNOT_HDG][0]+String.format(number_unsigned_format,hdg_deg)+"\n");
} else if (reserve_missing_fields){
sb.append("\n");
}
}
if ((annot_mode & (1 << ANNOT_MISM)) != 0){
if ((annot_mode & (1 << ANNOT_ERRB)) != 0){
double mismatch_before = target0[CuasMotionLMA.RSLT_MISMATCH_BEFORE];
// sb.append("ERRb"+String.format(number_frac_format,mismatch_before)+"\n");
sb.append(ANNOT_LABELS[ANNOT_ERRB][0]+String.format(number_frac_format,mismatch_before)+"\n");
}
if ((annot_mode & (1 << ANNOT_ERRA)) != 0){
double mismatch_after = target0[CuasMotionLMA.RSLT_MISMATCH_AFTER];
sb.append("ERRb"+String.format(number_frac_format,mismatch_before)+"\n");
sb.append("ERRa"+String.format(number_frac_format,mismatch_after)+"\n");
// sb.append("ERRa"+String.format(number_frac_format,mismatch_after)+"\n");
sb.append(ANNOT_LABELS[ANNOT_ERRA][0]+String.format(number_frac_format,mismatch_after)+"\n");
}
if ((annot_mode & (1 << ANNOT_SEQ)) != 0){
double sequence_length = target0[CuasMotionLMA.RSLT_MATCH_LENGTH];
sb.append("SEQ "+String.format(number_unsigned_format,sequence_length)+"\n");
// sb.append("SEQ "+String.format(number_unsigned_format,sequence_length)+"\n");
sb.append(ANNOT_LABELS[ANNOT_SEQ][0]+String.format(number_unsigned_format,sequence_length)+"\n");
}
if ((annot_mode & (1 << ANNOT_TRV)) != 0){
double sequence_travel = target0[CuasMotionLMA.RSLT_SEQ_TRAVEL];
sb.append("TRV "+String.format(number_frac_format,sequence_travel)+"\n");
// sb.append("TRV "+String.format(number_frac_format,sequence_travel)+"\n");
sb.append(ANNOT_LABELS[ANNOT_TRV][0]+String.format(number_frac_format,sequence_travel)+"\n");
}
if ((annot_mode & (1 << ANNOT_SCORE)) != 0){
double score = target0[CuasMotionLMA.RSLT_QSCORE];
sb.append("S "+String.format(number_frac_format,score)+"\n");
// sb.append("S "+String.format(number_frac_format,score)+"\n");
sb.append(ANNOT_LABELS[ANNOT_SCORE][0]+String.format(number_frac_format,score)+"\n");
}
// if (!Double.isInfinite(range)) {
return sb.toString();
}
/**
* Approximately calculate azimuth, elevation and angular velocities for far objects
* @param ersCorrection
* @param uasLogReader
* @param fps
* @param px
* @param py
* @param vx
* @param vy
* @return
*/
public static double [][] getPixToAzElev(
ErsCorrection ersCorrection,
UasLogReader uasLogReader,
double fps, // if NaN, will use default 60Hz. Used only for omegas
double px,
double py,
double vx,
double vy) {
return sb.toString();
if (Double.isNaN(fps)) {
fps = 60.0;
}
double [] camera_atr = uasLogReader.getCameraATR();
double ifov = ersCorrection.getIFOV();
int sensor_width = ersCorrection.getSensorWH()[0];
int sensor_height = ersCorrection.getSensorWH()[1];
double az = Double.NaN;
double el = Double.NaN;
az = (px - sensor_width/2) * ifov + camera_atr[0];
el = - (py - sensor_height/2) * ifov + camera_atr[1];
while (az < 0 ) az += 2*Math.PI;
while (az > 2*Math.PI ) az -= 2*Math.PI;
while (el > Math.PI) el -= 2* Math.PI;
while (el < -Math.PI) el += 2* Math.PI;
double az_deg = az * 180/Math.PI;
double el_deg = el * 180/Math.PI;
double omega_az = vx * ifov * fps;
double omega_el = -vy * ifov * fps;
double omega_az_degs = omega_az * 180/Math.PI;
double omega_el_degs = omega_el * 180/Math.PI;
return new double [][] {{az_deg,el_deg},{omega_az_degs,omega_el_degs}};
}
public static double interpolate (
double v0,
double v1,
......@@ -5490,7 +5642,7 @@ public class CuasMotion {
return; // imp_new;
}
//
private static int findMatchingTarget(
double [][] targets,
double [] uas_pXpYD,
......@@ -5521,64 +5673,6 @@ public class CuasMotion {
return s+ String.format(format, Math.abs(d));
}
public static String getTargetText(
CLTParameters clt_parameters,
GeometryCorrection gc,
double [] target) {
double [][] az_el_oaz_oel= getPixToAzElev(
clt_parameters, // CLTParameters clt_parameters,
gc, // GeometryCorrection gc,
target[TARGET_X], // double target_x,
target[TARGET_Y], // double target_y,
target[TARGET_VX], // double target_vx,
target[TARGET_VY]); // double target_vy);
String number_format = "%3.0f";
String omega_format = "%3.1f";
String omega = "\u03A9";
String txt = "";
txt += " ID "+String.format("%03d",(int) Math.round(target[TARGET_ID]))+"\n";
txt += " AZ "+String.format(number_format,az_el_oaz_oel[0][0])+"\n";
txt += " EL "+ getSignedDouble(az_el_oaz_oel[0][1],number_format)+"\n";
txt += omega+"AZ "+getSignedDouble(az_el_oaz_oel[1][0],omega_format)+"\n";
txt += omega+"EL "+getSignedDouble(az_el_oaz_oel[1][1],omega_format);
return txt;
}
// TODO: improve, get correct calculations with distortions
public static double [][] getPixToAzElev(
CLTParameters clt_parameters,
GeometryCorrection gc,
double target_x,
double target_y,
double target_vx,
double target_vy) {
double ifov = gc.getIFOVDegrees(); // clt_parameters.imp.cuas_ifov; // 0.05; // degree per pixel
int px0 = clt_parameters.imp.cuas_px0; // 283; // pixel with known azimuth
int py0 = clt_parameters.imp.cuas_py0; // 386; // pixel with known elevation
double az0 = clt_parameters.imp.cuas_az0; // 201.5; // degrees for cuas_px0;
double el0 = clt_parameters.imp.cuas_el0; // 0.0; // degrees for cuas_px0;
double fps = 60.0;
double az = (target_x - px0)*ifov+az0;
double el = -(target_y - py0)*ifov+el0;
double omega_az = target_vx * ifov * fps;
double omega_el = -target_vy * ifov * fps;
while (az < 0) {
az += 360;
}
while (az >= 360) {
az -= 360;
}
while (el < -180) {
el += 360;
}
while (el > 180) {
el -= 360;
}
return new double [][] {{az,el},{omega_az, omega_el}};
}
public static String saveAsVideo(
......@@ -5680,35 +5774,7 @@ public class CuasMotion {
final float [][] fpixels,
double [][][] target_sequence, // non-overlap only if consider marked stronger tiles
final int debugLevel) {
/*
generateExtractFilterMovingTargets( // move parameters to clt_parameters
clt_parameters, // CLTParameters clt_parameters,
video_pass, // final boolean video_pass, // if clt_parameters.cuas_clean_video=true, video_pass=0 - output TIFFS, but no video. If video_pass==1 - only video with no debug
batch_mode, // final boolean batch_mode,
parentCLT, //QuadCLT parentCLT, //
fpixels, // final float [][] fpixels,
target_sequence, // double [][][] target_sequence, // non-overlap only if consider marked stronger tiles
this, // CuasMotion cuasMotion,
uasLogReader, // UasLogReader uasLogReader,
scene_titles, // String [] scene_titles, // recreate slice_titles from scene titles?
slice_titles, // String [] slice_titles,
debugLevel); // final int debugLevel)
}
public static void generateExtractFilterMovingTargets( // move parameters to clt_parameters
CLTParameters clt_parameters,
final boolean video_pass, // if clt_parameters.cuas_clean_video=true, video_pass=0 - output TIFFS, but no video. If video_pass==1 - only video with no debug
final boolean batch_mode,
QuadCLT parentCLT, //
final float [][] fpixels,
double [][][] target_sequence, // non-overlap only if consider marked stronger tiles
CuasMotion cuasMotion,
UasLogReader uasLogReader,
String [] scene_titles, // recreate slice_titles from scene titles?
String [] slice_titles,
final int debugLevel) {
*/
String model_prefix = parentCLT.getImageName()+getParametersSuffixRslt(clt_parameters,null);
/// String model_prefix = parentCLT.getImageName()+getParametersSuffixRslt(clt_parameters,null);
boolean clean_video = clt_parameters.imp.cuas_clean_video; //true;// save video without any debug information for targets, output in TIFF files. False - same output for video and TIFFs
final int corr_offset = clt_parameters.imp.cuas_corr_offset;
......@@ -5735,37 +5801,14 @@ public class CuasMotion {
boolean intermed_high = clt_parameters.imp.cuas_intermed_high; // true;
boolean save_mono = clt_parameters.imp.cuas_save_mono; // true;
boolean save_color = clt_parameters.imp.cuas_save_color; // true;
boolean save_video = clt_parameters.imp.cuas_save_video; // true;
boolean target_debug = clt_parameters.imp.cuas_target_debug; // true;
boolean show_target_score = clt_parameters.imp.cuas_target_score; // false; // show target score and sequence length in the final video
boolean save_color0 = clt_parameters.imp.cuas_save_color; // true;
boolean save_video0 = clt_parameters.imp.cuas_save_video; // && video_pass; // true;
boolean annotate_uas = clt_parameters.imp.cuas_annotate_uas; // false; // show circle around UAS position from the flight log
boolean show_target_color = clt_parameters.imp.cuas_target_color; // false; // show target score and sequence length in the final video
boolean show_disp = clt_parameters.imp.cuas_show_disp; // true; // Show disparity (corrected) near target (*** not in clean***)
boolean show_rng = clt_parameters.imp.cuas_show_rng; // true; // Show distance to target (range) in meters
boolean show_inf = clt_parameters.imp.cuas_show_inf; // true; // Show distance greater than max (or negativce) as infinity
boolean show_inf_gt = clt_parameters.imp.cuas_show_inf_gt; // false; // Use ">max" instead of infinity symbol
boolean show_true_rng = clt_parameters.imp.cuas_show_true_rng; // show true range (from the flight log)
double radar_range = clt_parameters.imp.cuas_radar_range; // maximal radar range in meters
String clean_suffix = "";
if (clean_video) {
if (video_pass) {
annotate_uas = false;
save_mono = false;
save_color = false;
target_debug = false;
show_target_score = false;
show_target_color = false;
show_disp = false;
clean_suffix = "-CLEAN";
} else {
save_video = false;
}
}
boolean cuas_gaussian_ra = clt_parameters.imp.cuas_gaussian_ra; // use temporal Gaussian instead of running average
boolean center_targ = false; // clt_parameters.imp.cuas_center_targ;
boolean save_video = save_video0 && video_pass;
boolean save_color = save_color0 && !save_video;
int start_frame = 0;
int seq_length = corr_offset + corr_pairs;
......@@ -5817,7 +5860,7 @@ public class CuasMotion {
parentCLT.saveImagePlusInModelDirectory(imp_accumulated5x5); // ImagePlus imp)
}
double velocity_scale = 1.0/corr_offset;
double [][][] targets60hz = new double [fpixels.length][][];
// double [][][] targets60hz = new double [fpixels.length][][];
float [][] background = fpixels;
String ra_bg_suffix=(ra_background? ("-RABG"+corr_pairs):"");
if (ra_background) {
......@@ -5845,7 +5888,7 @@ public class CuasMotion {
frame0, // final int frame0,
corr_inc, // final int frame_step,
velocity_scale, // final double velocity_scale, // 1.0/(disparity in frames)
targets60hz, // final double [][][] targets60hz,
/// targets60hz, // final double [][][] targets60hz,
batch_mode, // final boolean batch_mode,
debugLevel); // final int debugLevel)
if (save_mono) {
......@@ -5862,24 +5905,19 @@ public class CuasMotion {
}
parentCLT.saveImagePlusInModelDirectory(imp_replaced_targets); // ImagePlus imp)
}
boolean clean_pass = clean_video && video_pass;
String clean_suffix = clean_pass? CLEAN_SUFFIX : "";
ImagePlus imp_color = convertToRgbAnnotateTargets(
clt_parameters, // CLTParameters clt_parameters,
clean_pass, // final boolean clean_pass,
input_range, // final double input_range, // 5
scale2x, // boolean scale2x,
target_type, // final int target_type, // = 0; // 0 - unknown, 1 - known, 2 - friend, 3 - foe
known_type, // final int known_type, // 2; // Target location matching UAS flight log: 0; // 0 - unknown, 1 - known, 2 - friend, 3 - foe
known_err, // final double known_err, // 20; // Maximal distance between the detected target and UAS log position (in raw image pixels);
replaced_targets, // final float [][] fpixels,
targets60hz, // final double [][][] targets60hz,
// targets60hz, // final double [][][] targets60hz,
show_target_color, // final boolean change_color,
show_disp, // final boolean show_disp, // true; // Show disparity (corrected) near target (*** not in clean***)
show_rng, // final boolean show_rng, // true; // Show distance to target (range) in meters
show_inf, // final boolean show_inf, // true; // Show distance greater than max (or negativce) as infinity
show_inf_gt, // final boolean show_inf_gt, // false; // Use ">max" instead of infinity symbol
show_true_rng, // final boolean show_true_rng,// show true range (from the flight log)
target_debug, // final boolean show_mismatch,
show_target_score, // final boolean show_score,
annotate_uas, // final boolean show_uas,
frame0, // final int frame0,
corr_inc, // final int frame_step,
......@@ -5894,19 +5932,19 @@ public class CuasMotion {
int height2 = imp_color.getHeight();
int width2 = (int) (16.0/9.0*height2);
int offset_x = width2 - imp_color.getWidth();
// ImagePlus imp_color2
imp_color= increaseCanvas(
imp_color, // ImagePlus imp, // color
width2, // int new_width,
height2, // int new_height,
offset_x, // int x0,
0); // int y0)
// imp_color2.show();
// parentCLT.saveImagePlusInModelDirectory(imp_color2);
// int annot_mode = 0xffffffbf;
int annot_mode = clt_parameters.imp.cuas_annot_sel[CuasMotion.ANNOT_RADAR_PANE_INDX];
if (video_pass) {
annot_mode &= ANNOT_DEFAULTS[ANNOT_CLEAN_VIEW_INDX]; //ANNOT_CLEAN;
annot_mode &= clt_parameters.imp.cuas_annot_sel[ANNOT_CLEAN_VIEW_INDX]; //ANNOT_CLEAN;
}
if (debugLevel > -4) {
System.out.println(String.format("Radar annotation mode 0x%04x (0x%04x & 0x%04x)",
annot_mode, clt_parameters.imp.cuas_annot_sel[CuasMotion.ANNOT_RADAR_PANE_INDX],clt_parameters.imp.cuas_annot_sel[ANNOT_CLEAN_VIEW_INDX]));
}
ImagePlus img_radar = generateRadarImage(
clt_parameters,
......
package com.elphel.imagej.cuas;
import java.awt.Color;
import java.awt.Font;
import java.awt.Point;
import java.awt.Rectangle;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
......@@ -16,12 +19,14 @@ import java.util.concurrent.atomic.AtomicInteger;
import com.elphel.imagej.cameras.CLTParameters;
import com.elphel.imagej.gpu.GPUTileProcessor;
import com.elphel.imagej.ims.UasLogReader;
import com.elphel.imagej.tileprocessor.ErsCorrection;
import com.elphel.imagej.tileprocessor.GeometryCorrection;
import com.elphel.imagej.tileprocessor.ImageDtt;
import com.elphel.imagej.tileprocessor.QuadCLT;
import ij.ImagePlus;
import ij.io.FileSaver;
import ij.process.ColorProcessor;
public class CuasMultiSeries {
......@@ -156,20 +161,282 @@ public class CuasMultiSeries {
}
}
public ImagePlus generateLegend(
int annot_mode,
String title) {
final int icon_to_text = 5; // pixels
final int inter_column = 20; // pixels
final boolean scale2x = true;
final double scale = scale2x ? 2 : 1;
// final double ifov = master_CLT.getGeometryCorrection().getIFOV();
// final double radar_range = clt_parameters.imp.cuas_radar_range;
final String font_name = clt_parameters.imp.cuas_font_name;
final int font_size_radar = clt_parameters.imp.cuas_font_size; // 7; //
// final double font_ratio_radar = clt_parameters.imp.cuas_font_spacing; // 1.2; // if 0 - will use default spacing ( ~=1.5)
final int font_type = clt_parameters.imp.cuas_font_type;
final Color text_color = clt_parameters.imp.cuas_text_color;
// final Color selected_color = text_color; // clt_parameters.imp.cuas_selected_color;
// final boolean transparent_other = clt_parameters.imp.cuas_transparent;
// final boolean transparent_uas = clt_parameters.imp.cuas_transparent_uas;
final int target_type = clt_parameters.imp.cuas_target_type; // 0; // 0 - unknown, 1 - known, 2 - friend, 3 - foe
final int uas_type = clt_parameters.imp.cuas_known_type; // 2; // Target location matching UAS flight log: 0; // 0 - unknown, 1 - known, 2 - friend, 3 - foe
final double uas_radius = clt_parameters.imp.cuas_radar_uas_rad;// 4.0;
final double target_radius = clt_parameters.imp.cuas_radar_radius; // 2.5;
final Color uas_color = clt_parameters.imp.cuas_radar_uas_color; // new Color( 0,100,140);
final Color target_color = clt_parameters.imp.cuas_radar_color; // new Color( 0,255,100);
// final boolean legend_include = clt_parameters.imp.cuas_legend_include;
final Color legend_title_color = clt_parameters.imp.cuas_legend_title_color;
final int legend_title_font = clt_parameters.imp.cuas_legend_title_font;
final int legend_font = clt_parameters.imp.cuas_legend_font;
final int legend_icons = clt_parameters.imp.cuas_legend_icons;
final double legend_spacing = clt_parameters.imp.cuas_legend_spacing;
final Rectangle rect_legend = clt_parameters.imp.cuas_legend;
final Color legend_description_color = legend_title_color;
final Color legend_acronyms_color = text_color;
// final double [] camera_atr = uasLogReader.getCameraATR();
// final ErsCorrection ersCorrection = master_CLT.getErsCorrection();
boolean annotate_uas = clt_parameters.imp.cuas_annotate_uas && (uasLogReader != null); // false; // show circle around UAS position from the flight log
// prepare UAS log icon (blue circle)
ColorProcessor uaslog_cp = annotate_uas? CuasMotion.getUasLogIconColorProcessor():null;
// prepare target icons
ColorProcessor cp_target_icon = CuasMotion.getIconColorProcessor(
target_type, // int target_type, // Target location matching UAS flight log: 0; // 0 - unknown, 1 - known, 2 - friend, 3 - foe
scale2x); // boolean scale2x)
ColorProcessor cp_uas_icon = CuasMotion.getIconColorProcessor(
uas_type, // uas_type, // int target_type, // Target location matching UAS flight log: 0; // 0 - unknown, 1 - known, 2 - friend, 3 - foe
scale2x); // boolean scale2x)
final int uaslog_width = (uaslog_cp != null) ? uaslog_cp.getWidth() : 0;
final int target_icon_width = cp_target_icon.getWidth();
final int uas_icon_width = cp_uas_icon.getWidth();
final int [] uaslog_pixels = (int[]) uaslog_cp.getPixels();
final int [] target_icon_pixels = (int[]) cp_target_icon.getPixels();
final int [] uas_icon_pixels = (int[]) cp_uas_icon.getPixels();
final int [][] uaslog_rgba = CuasMotion.splitColorIcon(uaslog_pixels);
final int [][] target_icon_rgba = CuasMotion.splitColorIcon(target_icon_pixels);
final int [][] uas_icon_rgba = CuasMotion.splitColorIcon(uas_icon_pixels);
final ColorProcessor cp_legend = new ColorProcessor(rect_legend.width, rect_legend.height);
int legend_width = rect_legend.width;
int [] legend_pixels = (int[]) cp_legend.getPixels();
int font_size_description = legend_font; // font_size_radar; // separate
Font font_title = new Font(font_name, font_type, (int) Math.round (scale * legend_title_font));
Font font_description = new Font(font_name, font_type, (int) Math.round (scale * font_size_description));
Font font_acronyms = new Font(font_name, font_type, (int) Math.round (scale * font_size_description)); // font_size_radar));
int vspace_annot = (int) Math.round (Math.max(font_size_description, font_size_radar) * scale * legend_spacing);
// Icons
double icon_half_width = 0;
icon_half_width = Math.max(uas_icon_width, 0.5*uaslog_width);
icon_half_width = Math.max(uas_icon_width, 0.5*target_icon_width);
icon_half_width = Math.max(uas_icon_width, 0.5*uas_icon_width);
icon_half_width = Math.max(uas_icon_width, uas_radius);
icon_half_width = Math.max(uas_icon_width, target_radius);
// TODO - find offset from abbreviations
cp_legend.setColor(legend_description_color);
cp_legend.setFont(font_description);
int x0 = rect_legend.x, y0 = rect_legend.y;
int y0_acronyms_center = rect_legend.y + legend_icons; // align first lines
int max_x = x0;
for (int nicon = 0; nicon < CuasMotion.ICON_DESCRIPTIONS.length; nicon++) {
y0 += legend_icons;
switch (nicon) {
case 0:
CuasMotion.imprintPixelIcon(
uas_icon_rgba, // int [][] icon,
uas_icon_pixels, // int [] icon_pix,
uas_icon_width, // int icon_width,
legend_pixels, // int [] image,
legend_width, // int width,
x0, // int xc,
y0); // int yc)
break;
case 1:
CuasMotion.imprintPixelIcon(
target_icon_rgba, // int [][] icon,
target_icon_pixels, // int [] icon_pix,
target_icon_width, // int icon_width,
legend_pixels, // int [] image,
legend_width, // int width,
x0, // int xc,
y0); // int yc)
break;
case 2:
CuasMotion.imprintPixelIcon(
uaslog_rgba, // int [][] icon,
uaslog_pixels, // int [] icon_pix,
uaslog_width, // int icon_width,
legend_pixels, // int [] image,
legend_width, // int width,
x0, // int xc,
y0); // int yc)
break;
case 3:
CuasMotion.drawCircle(
cp_legend, // ColorProcessor colorProcessor,
uas_color, // Color color, // or null
x0, // double xc,
y0, // double yc,
uas_radius); // double radius)
break;
case 4:
CuasMotion.drawCircle(
cp_legend, // ColorProcessor colorProcessor,
target_color, // Color color, // or null
x0, // double xc,
y0, // double yc,
target_radius); // double radius)
break;
}
// find the height
String txt = CuasMotion.ICON_DESCRIPTIONS[nicon]; // single-line
Rectangle txt_bound = cp_legend.getStringBounds(txt);
int y_descr = y0 - (txt_bound.y + txt_bound.height/2);
int x_descr = x0+((int) icon_half_width + icon_to_text);
max_x = Math.max(max_x, x_descr + txt_bound.x + txt_bound.width);
cp_legend.setColor(legend_description_color);
cp_legend.drawString(txt, x_descr, y_descr); // transparent bg
}
// create text description
// find longest short names
int acronyms_max_end = 0;
cp_legend.setFont(font_acronyms);
cp_legend.setColor(legend_acronyms_color);
int x0_acro = max_x + inter_column;
int num_acro = 0;
int [] acro_index = new int [CuasMotion.ANNOT_LABELS.length];
int [] acro_pos_y = new int [CuasMotion.ANNOT_LABELS.length];
Arrays.fill(acro_index, -1);
for (int i = 0; i < CuasMotion.ANNOT_LABELS.length; i++) if ((annot_mode & (1 << i)) != 0){
int i_base = i;
int y0_acro = y0_acronyms_center + num_acro * vspace_annot;
String txt = CuasMotion.ANNOT_LABELS[i][0];
if ((txt == null) && ((annot_mode & (1 << (i-1))) == 0)) { // if no elevation, but conditional_elevation is enabled
i_base = i-1;
txt = CuasMotion.ANNOT_LABELS[i_base][0]; // for conditional elevation
}
if (txt != null) {
Rectangle txt_bound = cp_legend.getStringBounds(txt);
int y_acro = y0_acro - (txt_bound.y + txt_bound.height/2);
cp_legend.drawString(txt, x0_acro, y_acro); // transparent bg
acronyms_max_end = Math.max(acronyms_max_end, x0_acro + txt_bound.x + txt_bound.width);
acro_index[i_base] = num_acro++;
acro_pos_y[i_base] = y_acro;
}
}
int x0_acro_descr = acronyms_max_end + icon_to_text;
cp_legend.setFont(font_description);
cp_legend.setColor(legend_description_color);
int acronyms_descr_end = x0_acro_descr;
for (int i = 0; i < CuasMotion.ANNOT_LABELS.length; i++) if (acro_index[i] >=0) { // ((annot_mode & (1 << i)) != 0){
String txt = CuasMotion.ANNOT_LABELS[i][2];
Rectangle txt_bound = cp_legend.getStringBounds(txt);
cp_legend.drawString(txt, x0_acro_descr, acro_pos_y[i]); // transparent bg
acronyms_descr_end = Math.max(acronyms_descr_end, x0_acro_descr + txt_bound.x + txt_bound.width);
}
// print title
// int x0 = rect_legend.x
{
String txt = CuasMotion.LEGEND_TITLE;
cp_legend.setColor(legend_title_color);
cp_legend.setFont(font_title);
Rectangle txt_bound = cp_legend.getStringBounds(txt);
int offs = (acronyms_descr_end-txt_bound.width)/2;
cp_legend.drawString(txt, rect_legend.x + offs, rect_legend.y); // transparent bg
}
ImagePlus imp_legend = new ImagePlus(title, cp_legend);
// imp_legend.show();
return imp_legend;
}
public void combineVideos() {
String videoDirectory = master_CLT.correctionsParameters.selectVideoDirectory(true,true);
String extra_suffix_with_radar = "-2";
// double video_fps = clt_parameters.imp.video_fps;
String video_codec_combo = clt_parameters.imp.video_codec.toLowerCase();
int video_crf_combo = clt_parameters.imp.video_crf;
double video_bitrate_m = clt_parameters.imp.video_bitrate_m;
int corr_pairs = clt_parameters.imp.cuas_corr_pairs;
boolean ra_background = clt_parameters.imp.cuas_ra_background; // true;
String ra_bg_suffix=(ra_background? ("-RABG"+corr_pairs):"");
String clean_suffix = "-CLEAN"; // CuasMotion.CLEAN_SUFFIX
boolean legend_include = clt_parameters.imp.cuas_legend_include;
double legend_duration = clt_parameters.imp.cuas_legend_duration;
if (videoDirectory == null) {
System.out.println("No video directory selected");
return;
}
File video_dir = new File (videoDirectory);
video_dir.mkdirs(); // Should already exist
int full_annot_mode = clt_parameters.imp.cuas_annot_sel[CuasMotion.ANNOT_RADAR_PANE_INDX] | // both panes
clt_parameters.imp.cuas_annot_sel[CuasMotion.ANNOT_IMAGE_PANE_INDX];
int clean_annot_mode = full_annot_mode & clt_parameters.imp.cuas_annot_sel[CuasMotion.ANNOT_CLEAN_VIEW_INDX];
ImagePlus [] imp_legends = new ImagePlus[2];
String [] legend_paths = new String[2];
for (int iclean = 0; iclean <2; iclean++) {
boolean clean = iclean > 0;
int annot_mode = clean ? clean_annot_mode : full_annot_mode;
// use first series name
String title = model_names[0]+"-LEGEND"+(clean?CuasMotion.CLEAN_SUFFIX: "")+".tiff";
imp_legends[iclean] = generateLegend(
annot_mode, // int annot_mode,
title); // String title));
legend_paths[iclean] = QuadCLT.saveImagePlusInDirectory(
imp_legends[iclean], // ImagePlus imp,
video_dir.toString()); // String dir)
}
File legend_vfile = null;
if (legend_include) { // only include clean legend
double pts_scale = clt_parameters.imp.video_fps/clt_parameters.imp.sensor_fps;
pts_scale = 1.0;
String legend_path = legend_paths[1];
String legend_vpath = legend_path;
int ind_dot = legend_vpath.lastIndexOf(".");
legend_vpath= legend_vpath.substring(0,ind_dot)+".webm";
legend_vfile = new File(legend_vpath);
String shell_legend_include = String.format("ffmpeg -y -loop 1 -i %s -r 60 -vf setpts=%f*PTS -b:v %fM -crf %d -c %s -t %f -pix_fmt yuv420p %s",
legend_paths[1],
pts_scale,
video_bitrate_m,
video_crf_combo,
video_codec_combo,
legend_duration,
legend_vpath);
boolean legend_ok = runShellCommand(
shell_legend_include, // String shellCommand,
video_dir, // File work_dir,
legend_vfile);
if (!legend_ok) {
legend_vfile = null;
}
}
System.out.println();
ArrayList<String> video_paths = new ArrayList<String>();
if ((legend_vfile != null)&& legend_vfile.exists()) {
video_paths.add(legend_vfile.toString());
}
// int annot_mode = -1; // specify bits
int corr_pairs = clt_parameters.imp.cuas_corr_pairs;
boolean ra_background = clt_parameters.imp.cuas_ra_background; // true;
String ra_bg_suffix=(ra_background? ("-RABG"+corr_pairs):"");
String clean_suffix = "-CLEAN";
for (int nser = 0; nser < model_names.length; nser++) {
String image_name = model_names[nser];
String webm_title = image_name+CuasMotion.getParametersSuffixRslt(clt_parameters,"-RGB"+ra_bg_suffix+clean_suffix)+extra_suffix_with_radar+".webm";
......@@ -180,13 +447,6 @@ public class CuasMultiSeries {
}
}
System.out.println("Combining "+video_paths.size()+" video files.");
String videoDirectory = master_CLT.correctionsParameters.selectVideoDirectory(true,true);
if (videoDirectory == null) {
System.out.println("No video directory selected");
return;
}
File video_dir = new File (videoDirectory);
video_dir.mkdirs(); // Should already exist
String combo_video_name = "COMBO"+CuasMotion.getParametersSuffixRslt(clt_parameters,"-RGB"+ra_bg_suffix+clean_suffix)+extra_suffix_with_radar+".webm";
String concat_list_name = combo_video_name.substring(0, combo_video_name.lastIndexOf("."))+".list";
......@@ -234,6 +494,12 @@ public class CuasMultiSeries {
shellCommand = String.format("ffmpeg -y -f concat -safe 0 -i %s -r 60 -vf setpts=%f*PTS -b:v %fM -crf %d -c %s %s",
list_to_concat.toString(), pts_scale, video_bitrate_m, video_crf_combo, video_codec_combo, video_out.toString());
boolean shell_ok = runShellCommand(
shellCommand, // String shellCommand,
video_dir, // File work_dir,
video_out); // File out_file) { // if not null will delete this file and verify its creation
/*
Process p = null;
int exit_code = -1;
System.out.println("Will run shell command: \""+shellCommand+"\"");
......@@ -262,10 +528,60 @@ public class CuasMultiSeries {
if ((exit_code != 0) || !video_out.exists()) {
System.out.println("Failed to create : \""+video_out.toString()+"\"");
}
*/
System.out.println("All "+(shell_ok? "done":"failed"));
return;
}
public boolean runShellCommand(
String shellCommand,
File work_dir,
File out_file) { // if not null will delete this file and verify its creation
if ((out_file != null) && out_file.exists()) {
out_file.delete();
}
Process p = null;
int exit_code = -1;
System.out.println("Will run shell command: \""+shellCommand+"\"");
System.out.println("This may take a while, please wait ...");
try {
p = Runtime.getRuntime().exec(
shellCommand,
null, // env
work_dir // working dir - needed if "-report" is added to ffmpeg command
);
} catch (IOException e) {
System.out.println("Failed shell command: \""+shellCommand+"\"");
}
if (p != null) {
try {
p.waitFor();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
exit_code = p.exitValue();
}
System.out.println("Ran shell command: \""+shellCommand+"\" -> ");
if ((exit_code != 0) || ((out_file != null) && !out_file.exists())) {
System.out.println("Failed to create output in : \""+work_dir.toString()+"\"");
return false;
} else {
//out_file
if (out_file != null) {
System.out.println("Created : \""+out_file.toString()+" in \""+work_dir.toString()+"\"");
} else {
System.out.println("Finished w/o errors in \""+work_dir.toString()+"\"");
}
return true;
}
}
public void processGlobals() {
int debugLevel = 0;
int setup_uas = setupUasTiles();
......@@ -297,7 +613,7 @@ public class CuasMultiSeries {
//
ImagePlus imp_radar = testGenerateRadarImage(
clt_parameters, // CLTParameters clt_parameters,
45, // 3, // 15, // int nser,
15, // 45, // 3, // 15, // int nser,
uasLogReader, // UasLogReader uasLogReader, // contains camera orientation (getCameraATR())
debugLevel); // int debugLevel) {
return;
......
......@@ -241,6 +241,7 @@ public class CuasRanging {
targets = disparity_targets;
System.out.println("processMovingTargetsMulti(): re-using target disparities from "+disparity_path+", generating radar mode images");
}
cuasMotion.setTargets(targets);
} else {
cuasMotion.processMovingTargetsMulti( // will remove rendering
batch_mode, // final boolean batch_mode,
......@@ -326,8 +327,8 @@ public class CuasRanging {
cuasMotion.getTilesX()); // int tilesX) {
center_CLT.saveImagePlusInModelDirectory(imp_with_range); // ImagePlus imp)
}
} else if (recalc_target_id){// if (disparity_targets == null) {
cuasMotion.recalcOmegas(
} else if (recalc_target_id){// if (disparity_targets == null) { // at com.elphel.imagej.cuas.CuasMotion$46.run(CuasMotion.java:7269)
cuasMotion.recalcOmegas( // does not work -
false, // boolean recalc,
targets, // final double [][][] target_single_in,
batch_mode, // boolean batch_mode,
......@@ -2761,18 +2762,21 @@ public class CuasRanging {
sb.append("\n"); // there will be 1 extra blank column
String [] slice_titles = cuasMotion.getSliceTitles(); // timestamps
UasLogReader uasLogReader = cuasMotion.getUasLogReader();
ErsCorrection ersCorrection = center_CLT.getErsCorrection();
for (int nseq = 0; nseq < num_seq; nseq++) {
String timestamp = slice_titles[nseq];
sb.append(nseq+"\t"+timestamp+"\t");
// get azimuth, elevation, target disparity from the log plus infinity, log range
double [] uas_pXpYDRange = uasLogReader.getUasPxPyDRange(timestamp); // px, py, d- cuas_infinity (true disparity), range
double [][] az_el_oaz_oel= CuasMotion.getPixToAzElev(
clt_parameters, // CLTParameters clt_parameters,
gc, // GeometryCorrection gc,
ersCorrection, // ErsCorrection ersCorrection,
uasLogReader, // UasLogReader uasLogReader,
Double.NaN, // double fps, // if NaN, will use default 60Hz. Used only for omegas
uas_pXpYDRange[0], // double target_x,
uas_pXpYDRange[1], // double target_y,
0, // double target_vx,
0); // double target_vy);
sb.append(uas_pXpYDRange[0]+"\t"+uas_pXpYDRange[1]+"\t"+az_el_oaz_oel[0][0]+"\t"+az_el_oaz_oel[0][1]+"\t"+(uas_pXpYDRange[2]+cuas_infinity)+"\t"+uas_pXpYDRange[3]+"\t");
for (int ntarg = 0; ntarg < num_targets; ntarg++) {
......@@ -2793,15 +2797,16 @@ public class CuasRanging {
double yc = tileSize * tileY + tileSize/2 + target[CuasMotionLMA.RSLT_Y];
double vx = target[CuasMotionLMA.RSLT_VX];
double vy = target[CuasMotionLMA.RSLT_VY];
// calculate and output target azimuth, elevation, disparity (full) and range
az_el_oaz_oel= CuasMotion.getPixToAzElev(
clt_parameters, // CLTParameters clt_parameters,
gc, // GeometryCorrection gc,
xc, // double target_x, // null
yc, // double target_y,
vx, // double target_vx,
vy); // double target_vy);
ersCorrection, // ErsCorrection ersCorrection,
uasLogReader, // UasLogReader uasLogReader,
Double.NaN, // double fps, // if NaN, will use default 60Hz. Used only for omegas
xc, // double px, // null
yc, // double py,
vx, // double vx,
vy); // double vy);
sb.append(xc+"\t"+yc+"\t"+az_el_oaz_oel[0][0]+"\t"+az_el_oaz_oel[0][1]+"\t"+
target[CuasMotionLMA.RSLT_DISPARITY]+"\t"+target[CuasMotionLMA.RSLT_RANGE]+"\t");
if (target[CuasMotionLMA.RSLT_GLENGTH] > 0) {
......
......@@ -49,6 +49,7 @@ public class IntersceneMatchParameters {
public static Color DEFAULT_cuas_radar_uas_color =new Color( 0,100,140);
public static Color DEFAULT_cuas_radar_color = new Color( 0,255,100);
public static Color DEFAULT_cuas_grid_color = new Color(100,100,100);
public static Color DEFAULT_cuas_legend_color =new Color( 255,255,255); // legend title color
......@@ -881,18 +882,18 @@ min_str_neib_fpn 0.35
public double cuas_font_spacing = 1.2; //height to size ratio. If 0 - will use default spacing ( ~=1.5)
public boolean cuas_annot_missing = false; // Reserve a line for requested but missing parameters
// AZ/EL calibration
@Deprecated
public double cuas_ifov = 0.05; // degree per pixel Use gc.getIFOVDegrees() and gc.getIFOV() instead
public int cuas_px0 = 283; // pixel with known azimuth
public int cuas_py0 = 386; // pixel with known elevation
public double cuas_az0 = 201.5; // degrees for cuas_px0;
public double cuas_el0 = 0.0; // degrees for cuas_px0;
public boolean cuas_show_disp = true; // Show disparity (corrected) near target (not in clean)
public boolean cuas_show_rng = true; // Show distance to target (range) in meters
public boolean cuas_legend_generate = true; //
public boolean cuas_legend_include = true; // include legend in the video
public double cuas_legend_duration = 5.0; // seconds in the beginning of the video
public Color cuas_legend_title_color = DEFAULT_cuas_legend_color;
public int cuas_legend_title_font = 18;
public int cuas_legend_font = 10; // before scaling 2x (to match other sizes)
public int cuas_legend_icons = 60; // icons vertical spacing, pixels
public double cuas_legend_spacing = 1.5; // height to size ratio. If 0 - will use default spacing ( ~=1.5)
public Rectangle cuas_legend = new Rectangle(50, 150, 1820, 1024); // Legend location and image size (same as video)
public boolean cuas_show_inf = true; // Show distance greater than max (or negativce) as infinity
public boolean cuas_show_inf_gt = true; // Use ">max" instead of infinity symbol
public boolean cuas_show_true_rng = true; // show true range (from the flight log)
// ranging parameters
public boolean cuas_smooth_omegas = true; // Recalculate omegas from continuing targets positions
......@@ -966,7 +967,7 @@ min_str_neib_fpn 0.35
public Color cuas_radar_uas_color = DEFAULT_cuas_radar_uas_color; // new Color( 0,100,140); True UAS position sircle
public Color cuas_radar_color = DEFAULT_cuas_radar_color; //new Color( 0,255,100); Detected color
public double cuas_radar_radius = 2.5;
public double cuas_radar_uas_rad = 4.0;
public double cuas_radar_uas_rad = 7.0; // 4.0;
// parameters for "radar" grid generation
public double cuas_grid_ring = 100.0; // (m) range rings step in meters
public double cuas_grid_line = 5.0; // (deg) grid axial directions step
......@@ -2717,26 +2718,33 @@ min_str_neib_fpn 0.35
"Height to size ratio. If 0 - will use default spacing ( ~=1.5).");
gd.addCheckbox ("Reserve lines for undefined parameters", this.cuas_annot_missing,
"Reserve line for requested but missing parameters.");
gd.addNumericField("Known image pixel X coordinate", this.cuas_px0, 0,3,"",
"Image pixel X corresponding to the known azimuth.");
gd.addNumericField("Known image pixel X coordinate", this.cuas_py0, 0,3,"",
"Image pixel Y corresponding to the known elevation.");
gd.addNumericField("Known pixel azimuth", this.cuas_az0, 5,8,"degree",
"Azimuth corresponding to the known pixel X.");
gd.addNumericField("Known pixel elevation", this.cuas_el0, 5,8,"degree",
"Elevation corresponding to the known pixel Y.");
gd.addCheckbox ("Show target disparity", this.cuas_show_disp,
"Show disparity before infinity correction (not in clean mode).");
gd.addCheckbox ("Show target distance (meters)", this.cuas_show_rng,
"Show range true from the UAS log.");
gd.addMessage("=== Legend generation === ");
gd.addCheckbox ("Generate legend", this.cuas_legend_generate,
"Generate legend in the same directory as composite video when genarating composite video.");
gd.addCheckbox ("Include legend in video", this.cuas_legend_include,
"Include generated legend in the beginning of the composite video.");
gd.addNumericField("Legend duration in video", this.cuas_legend_duration, 5,8,"s",
"Legend duration, in seconds");
gd.addStringField ("Legend title color", getStringColor(this.cuas_legend_title_color, DEFAULT_cuas_legend_color), 8,
"legend font color. Any wrong hex value will be replaced by the default - "+getStringColor(DEFAULT_cuas_legend_color));
gd.addNumericField("Legend title font size", this.cuas_legend_title_font, 0,3,"",
"Actual font size will be double that as we are using fixed scale = 2.0 for all images.");
gd.addNumericField("Legend font size", this.cuas_legend_font, 0,3,"",
"Actual font size will be double that as we are using fixed scale = 2.0 for all images.");
gd.addNumericField("Legend icons spacing", this.cuas_legend_icons, 0,3,"pix",
"Vertical spacing between legend icons");
gd.addNumericField("Legend font spacing", this.cuas_legend_spacing, 5,8,"x",
"Height to size ratio. If 0 - will use default spacing ( ~=1.5).");
gd.addStringField ("Legend offset and image size", rectangleToString(cuas_legend), 40, "Legend title offset from the top-left corner and image sized.");
gd.addMessage("=== Ranging parameters ===");
gd.addCheckbox ("Show infinity distance to target", this.cuas_show_inf,
"Show when distance is above limit (unchecked - skip the line).");
gd.addCheckbox ("Show infinity as >range_limit", this.cuas_show_inf_gt,
"Show infinity as >range_limit, unchecked - as infinity symbol.");
gd.addCheckbox ("Show true range", this.cuas_show_true_rng,
"Show range true from the UAS log.");
gd.addMessage("=== Ranging parameters ===");
gd.addCheckbox ("Smooth omegas", this.cuas_smooth_omegas,
"Recalculate omegas from continuing targets positions.");
gd.addCheckbox ("Apply unsharp mask to images for ranging", this.cuas_rng_um,
......@@ -2889,12 +2897,12 @@ min_str_neib_fpn 0.35
gd.addMessage(CuasMotion.ANNOT_TIP);
for (int i = 0; i < CuasMotion.ANNOT_LABELS.length; i++) {
gd.addStringField(
CuasMotion.ANNOT_LABELS[i][0], // String label,
CuasMotion.ANNOT_LABELS[i][1], // String label,
CuasMotion.getCuasAnnot ( //String value,
i, // int indx,
cuas_annot_sel), // int [] annots),
8, // int width,
CuasMotion.ANNOT_LABELS[i][1]); // String tooltip)
CuasMotion.ANNOT_LABELS[i][2]); // String tooltip)
}
gd.addMessage("=== Debug ===");
......@@ -4061,15 +4069,21 @@ min_str_neib_fpn 0.35
this.cuas_font_type = (int) gd.getNextNumber();
this.cuas_font_spacing = gd.getNextNumber();
this.cuas_annot_missing = gd.getNextBoolean();
this.cuas_px0 = (int) gd.getNextNumber();
this.cuas_py0 = (int) gd.getNextNumber();
this.cuas_az0 = gd.getNextNumber();
this.cuas_el0 = gd.getNextNumber();
this.cuas_show_disp = gd.getNextBoolean();
this.cuas_show_rng = gd.getNextBoolean();
this.cuas_legend_generate = gd.getNextBoolean();
this.cuas_legend_include = gd.getNextBoolean();
this.cuas_legend_duration = gd.getNextNumber();
this.cuas_legend_title_color = getColorFromHex(
gd.getNextString(), //String hex_color,
DEFAULT_cuas_legend_color); // Color default_color)
this.cuas_legend_title_font = (int) gd.getNextNumber();
this.cuas_legend_font = (int) gd.getNextNumber();
this.cuas_legend_icons = (int) gd.getNextNumber();
this.cuas_legend_spacing = gd.getNextNumber();
this.cuas_legend = stringToRectangle(gd.getNextString());// Rectangle
this.cuas_show_inf = gd.getNextBoolean();
this.cuas_show_inf_gt = gd.getNextBoolean();
this.cuas_show_true_rng = gd.getNextBoolean();
this.cuas_smooth_omegas = gd.getNextBoolean();
this.cuas_rng_um = gd.getNextBoolean();
......@@ -5211,15 +5225,19 @@ min_str_neib_fpn 0.35
properties.setProperty(prefix+"cuas_font_type", this.cuas_font_type+""); // int
properties.setProperty(prefix+"cuas_font_spacing", this.cuas_font_spacing+""); // double
properties.setProperty(prefix+"cuas_annot_missing", this.cuas_annot_missing+""); // boolean
properties.setProperty(prefix+"cuas_px0", this.cuas_px0+""); // int
properties.setProperty(prefix+"cuas_py0", this.cuas_py0+""); // int
properties.setProperty(prefix+"cuas_az0", this.cuas_az0+""); // double
properties.setProperty(prefix+"cuas_el0", this.cuas_el0+""); // double
properties.setProperty(prefix+"cuas_show_disp", this.cuas_show_disp+""); // boolean
properties.setProperty(prefix+"cuas_show_rng", this.cuas_show_rng+""); // boolean
properties.setProperty(prefix+"cuas_legend_generate", this.cuas_legend_generate+""); // boolean
properties.setProperty(prefix+"cuas_legend_include", this.cuas_legend_include+""); // boolean
properties.setProperty(prefix+"cuas_legend_duration", this.cuas_legend_duration+""); // double
properties.setProperty(prefix+"cuas_legend_title_color", getStringColor(this.cuas_legend_title_color, DEFAULT_cuas_legend_color)); // Color
properties.setProperty(prefix+"cuas_legend_title_font", this.cuas_legend_title_font+"");// int
properties.setProperty(prefix+"cuas_cuas_legend_font", this.cuas_legend_font+""); // int
properties.setProperty(prefix+"cuas_legend_icons", this.cuas_legend_icons+""); // int
properties.setProperty(prefix+"cuas_legend_spacing", this.cuas_legend_spacing+""); // double
properties.setProperty(prefix+"cuas_legend", rectangleToString(cuas_legend)+""); // Rectangle
properties.setProperty(prefix+"cuas_show_inf", this.cuas_show_inf+""); // boolean
properties.setProperty(prefix+"cuas_show_inf_gt", this.cuas_show_inf_gt+""); // boolean
properties.setProperty(prefix+"cuas_show_true_rng", this.cuas_show_true_rng+""); // boolean
properties.setProperty(prefix+"cuas_smooth_omegas", this.cuas_smooth_omegas+""); // boolean
properties.setProperty(prefix+"cuas_rng_um", this.cuas_rng_um+""); // boolean
......@@ -6323,15 +6341,22 @@ min_str_neib_fpn 0.35
if (properties.getProperty(prefix+"cuas_font_type")!=null) this.cuas_font_type=Integer.parseInt(properties.getProperty(prefix+"cuas_font_type"));
if (properties.getProperty(prefix+"cuas_font_spacing")!=null) this.cuas_font_spacing=Double.parseDouble(properties.getProperty(prefix+"cuas_font_spacing"));
if (properties.getProperty(prefix+"cuas_annot_missing")!=null) this.cuas_annot_missing=Boolean.parseBoolean(properties.getProperty(prefix+"cuas_annot_missing"));
if (properties.getProperty(prefix+"cuas_px0")!=null) this.cuas_px0=Integer.parseInt(properties.getProperty(prefix+"cuas_px0"));
if (properties.getProperty(prefix+"cuas_py0")!=null) this.cuas_py0=Integer.parseInt(properties.getProperty(prefix+"cuas_py0"));
if (properties.getProperty(prefix+"cuas_az0")!=null) this.cuas_az0=Double.parseDouble(properties.getProperty(prefix+"cuas_az0"));
if (properties.getProperty(prefix+"cuas_el0")!=null) this.cuas_el0=Double.parseDouble(properties.getProperty(prefix+"cuas_el0"));
if (properties.getProperty(prefix+"cuas_show_disp")!=null) this.cuas_show_disp=Boolean.parseBoolean(properties.getProperty(prefix+"cuas_show_disp"));
if (properties.getProperty(prefix+"cuas_show_rng")!=null) this.cuas_show_rng=Boolean.parseBoolean(properties.getProperty(prefix+"cuas_show_rng"));
if (properties.getProperty(prefix+"cuas_legend_generate")!=null) this.cuas_legend_generate=Boolean.parseBoolean(properties.getProperty(prefix+"cuas_legend_generate"));
if (properties.getProperty(prefix+"cuas_legend_include")!=null) this.cuas_legend_include=Boolean.parseBoolean(properties.getProperty(prefix+"cuas_legend_include"));
if (properties.getProperty(prefix+"cuas_legend_duration")!=null) this.cuas_legend_duration=Double.parseDouble(properties.getProperty(prefix+"cuas_legend_duration"));
if (properties.getProperty(prefix+"cuas_legend_title_color")!=null) this.cuas_radar_uas_color = getColorFromHex(
properties.getProperty(prefix+"cuas_legend_title_color"), // String hex_color,
DEFAULT_cuas_legend_color); // Color default_color)
if (properties.getProperty(prefix+"cuas_legend_title_font")!=null) this.cuas_legend_title_font=Integer.parseInt(properties.getProperty(prefix+"cuas_legend_title_font"));
if (properties.getProperty(prefix+"cuas_legend_font")!=null) this.cuas_legend_font=Integer.parseInt(properties.getProperty(prefix+"cuas_legend_font"));
if (properties.getProperty(prefix+"cuas_legend_icons")!=null) this.cuas_legend_icons=Integer.parseInt(properties.getProperty(prefix+"cuas_legend_icons"));
if (properties.getProperty(prefix+"cuas_legend_spacing")!=null) this.cuas_legend_spacing=Double.parseDouble(properties.getProperty(prefix+"cuas_legend_spacing"));
if (properties.getProperty(prefix+"cuas_legend")!=null) this.cuas_legend=stringToRectangle((String) properties.getProperty(prefix+"cuas_legend"));
if (properties.getProperty(prefix+"cuas_show_inf")!=null) this.cuas_show_inf=Boolean.parseBoolean(properties.getProperty(prefix+"cuas_show_inf"));
if (properties.getProperty(prefix+"cuas_show_inf_gt")!=null) this.cuas_show_inf_gt=Boolean.parseBoolean(properties.getProperty(prefix+"cuas_show_inf_gt"));
if (properties.getProperty(prefix+"cuas_show_true_rng")!=null) this.cuas_show_true_rng=Boolean.parseBoolean(properties.getProperty(prefix+"cuas_show_true_rng"));
if (properties.getProperty(prefix+"cuas_smooth_omegas")!=null) this.cuas_smooth_omegas=Boolean.parseBoolean(properties.getProperty(prefix+"cuas_smooth_omegas"));
if (properties.getProperty(prefix+"cuas_rng_um")!=null) this.cuas_rng_um=Boolean.parseBoolean(properties.getProperty(prefix+"cuas_rng_um"));
......@@ -7430,15 +7455,19 @@ min_str_neib_fpn 0.35
imp.cuas_font_type = this.cuas_font_type;
imp.cuas_font_spacing = this.cuas_font_spacing;
imp.cuas_annot_missing = this.cuas_annot_missing;
imp.cuas_px0 = this.cuas_px0;
imp.cuas_py0 = this.cuas_py0;
imp.cuas_az0 = this.cuas_az0;
imp.cuas_el0 = this.cuas_el0;
imp.cuas_show_disp = this.cuas_show_disp;
imp.cuas_show_rng = this.cuas_show_rng;
imp.cuas_legend_generate = this.cuas_legend_generate;
imp.cuas_legend_include = this.cuas_legend_include;
imp.cuas_legend_duration = this.cuas_legend_duration;
imp.cuas_legend_title_color = this.cuas_legend_title_color;
imp.cuas_legend_title_font = this.cuas_legend_title_font;
imp.cuas_legend_font = this.cuas_legend_font;
imp.cuas_legend_icons = this.cuas_legend_icons;
imp.cuas_legend_spacing = this.cuas_legend_spacing;
imp.cuas_legend = new Rectangle(this.cuas_legend);
imp.cuas_show_inf = this.cuas_show_inf;
imp.cuas_show_inf_gt = this.cuas_show_inf_gt;
imp.cuas_show_true_rng = this.cuas_show_true_rng;
imp.cuas_smooth_omegas = this.cuas_smooth_omegas;
imp.cuas_rng_um = this.cuas_rng_um;
......
......@@ -6089,6 +6089,27 @@ public class QuadCLTCPU {
return file_path;
}
public static String saveImagePlusInDirectory(
ImagePlus imp,
String dir) {
String file_name = imp.getTitle();
if (!file_name.endsWith(".tiff")) {
file_name +=".tiff";
}
if (!dir.endsWith(Prefs.getFileSeparator())) {
dir += Prefs.getFileSeparator();
}
String file_path = dir + file_name; // + ".tiff";
FileSaver fs=new FileSaver(imp);
fs.saveAsTiff(file_path); // image processor null?
System.out.println("saveImagePlusInDirectory(): saved "+file_path);
return file_path;
}
/*
File list_to_concat = new File (video_dir,concat_list_name);
*/
public String saveConfInModelDirectory()
{
String x3d_path = getX3dDirectory();
......
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