File Formats¶
The following file formats are used by the uPSP processing software.
High-speed camera video formats¶
The uPSP software supports the following vendor-specific files:
CINE files (from Phantom Vision cameras)
MRAW/CIH files (from Photron cameras)
In particular, the software is tested primarily with monochannel, “12-bit packed” images. Other packing strategies are supported but are less commonly used.
Surface grid definition¶
The uPSP software requires an accurate definition of the wind tunnel model wetted surfaces. It currently supports two file formats, auto-detected based on file extension:
*.g
,*.x
,*.grid
,*.grd
: PLOT3D structured grid*.tri
: Cart3D unstructured grid
The following subsections provide more detail for each grid file format.
PLOT3D file formats¶
PLOT3D is a computer graphics program (written at NASA) to visualize the grids and solutions of computational fluid dynamics. The program defined several file formats that are now industry standard; in particular, refer to PLOT3D User Manual, Chapter 8: Data File Formats. The uPSP software processes the following subset of PLOT3D file formats:
3D Grid XYZ file (
*.grd
,*.x
,*.g
) (PLOT3D User Manual, Section 8.2)Unformatted FORTRAN (binary, and contains leading- and trailing- 32-bit record separators)
Multi-grid
Single precision
No IBLANKS
3D Function file (
*.p3d
,*.f
) (PLOT3D User Manual, Section 8.4)Unformatted FORTRAN (binary, and contains leading- and trailing- 32-bit record separators)
Multi-grid
Single precision
Assumes only one scalar variable per vertex (in user manual,
NVAR=1
)
Note that the uPSP software does not ingest solution files (*.q
),
which normally contain values for the full flow variable solution at
each grid point. Solution files are more commonly produced by CFD
solvers and are occasionally confused with function files.
Cart3D file formats¶
Cart3D is a high-fidelity inviscid analysis package (written at NASA) for conceptual and preliminary aerodynamic design. The package defined several grid file formats that are now industry standard. The uPSP software processes the following subset of Cart3D file formats:
Surface triangulations (
*.tri
) for 3D surface geometry definitionAnnotated triangulations (
*.triq
) for scalar values defined over a surface triangulation
“Targets” file (*.tgts
)¶
In addition to a specification of the model surface geometry, the uPSP software must be provided a file that specifies:
The 3D position and normal for visible key points on the model surface, known as targets
These key points must be dark regions on the model surface where paint was either not applied to purposefully darked with a stain
Circular surface regions (position + diameter) where paint is not present or is damaged
The targets locations must be outside the model grid by a distance of 1e-5 +/- 5e-6 inches.
The file format is commonly called the “targets” file and is defined by the DOTS application, a steady-state PSP solver application used at NASA, but should be modified to ensure the targets are consistent with the grid file. An example is included below.
Targets File Example:
# x y z normal x normal y normal z size i j k name
1 67.02449799 3.17536973 -2.70057420 0.000000 0.762017 -0.647557 0.433 596 21 55 st6
2 66.52809906 2.83113538 3.05953808 0.000000 0.678209 0.734869 0.433 596 85 50 st7
3 79.28500366 7.62883166 -1.21192827 0.000420 0.742280 -0.670089 0.433 2261 160 26 st8
4 79.03060150 7.57744602 1.26724449 -0.000430 0.718970 0.695040 0.433 2261 20 23 st9
5 81.26619721 2.67079590 3.20469503 0.000000 0.641469 0.767148 0.433 716 29 25 st10
6 95.46779633 7.70066046 1.12676893 0.000000 0.786289 0.617859 0.433 2260 17 30 st11
7 98.17250061 2.85770474 3.03950497 0.000000 0.677413 0.735603 0.433 716 189 27 st12
8 110.63110352 7.77465312 1.02533593 0.000000 0.826620 0.562760 0.433 2260 15 224 st13
Steady-state surface pressure file¶
The uPSP software requires a reference, steady-state surface pressure at each grid point in order to compute the unsteady fluctuating pressure. It supports the following file formats for ingesting steady-state pressure data, auto-detected by file extension. It is also dependent on the format used for the model grid file.
PLOT3D function file (
*.f
,*.p3d
) if the model grid is PLOT3D structuredCart3D annotated triangulation (
*.triq
) if the model grid is Cart3D unstructured
See PLOT3D file formats and Cart3D file formats for more details. In both formats, the scalar values should be provided as values of the coefficient of pressure (\(C_p\)).
Wind Tunnel Data (*.wtd
)¶
During operations at the NASA Ames UPWT Complex 11-ft test section,
time-averaged values for positioning of the model in the test
section and current flow conditions are provided
by the wind tunnel data systems via a simple, human-readable
text file simply called the Wind Tunnel Data (*.wtd
) file.
An example WTD file is shown below. Tunnel data system values are written tab-delimited with their name in the corresponding header column.
# MACH ALPHA BETA PHI STRUTZ_UNC
0.838751 -0.041887 0.011826 -90.000000 3.012192
There are several uPSP applications that make use of data from this file:
The wind-on external calibration step requires an initial guess of the model positioning in the test section
The “intensity-to-pressure” paint calibration process requires the steady-state flow conditions for empirical estimates of the model surface temperature in cases where a per-grid-point temperature input file is not provided
The uPSP applications make use of the following columns from the WTD file (which may have many more columns that are ignored by the uPSP code):
STRUTZ_UNC
: (Uncorrected) “strutz” position, or current Z-coordinate of the model strutALPHA
: (Corrected) Model pitch angleBETA
: (Corrected) Model sideslip anglePHI
: (Corrected) Model roll angle
The model angles are “corrected” by the wind tunnel data system to account for additional bending due to deflection of the sting and model mounting system. All coordinates and angles are consistent with definitions published by NASA for the 11-ft test section. Technical details about the NASA Ames 11-ft test section, including coordinate system definitions and naming conventions, are published online by NASA (see Unitary Plan Wind Tunnel 11-by 11-foot TWT Test Section).
Unsteady PSP gain calibration¶
The uPSP software requires a pre-computed calibration for converting intensity ratios from camera pixel values into physical units of pressure.
The calibration has 6 coefficients (a
, b
, c
, d
, e
,
f
) that should be provided in a plain text file, example as follows:
a = 1.1
b = 2.2
c = 3.3
d = 4.4
e = 5.5
f = 6.6
See Phase 2 processing for their usage in a polynomial relation between pressure, temperature, and the unsteady gain value.
Camera-to-tunnel calibration¶
The camera-to-tunnel calibration file contains the intrinsic camera parameters as well as the extrinsic camera parameters relative to the tunnel origin. It is a JSON file with the following elements:
uPSP_cameraMatrix
: Camera Matrix formatted as[[f, 0, dcx], [0, f, dcy], [0, 0, 1]]
, where f is the focal length (in pixels), and (dcx, dcy) is the vector in pixel space from the image center to the principal point.distCoeffs
: OpenCV 5-parameter lens distortion coefficients formatted as[k1, k2, p1, p2, k3]
rmat
: rotation matrix from camera to tunneltvec
: translation vector from camera to tunnel
Optional:
sensor_resolution
: Camera sensor resolutionsensor_size
: Camera sensor physical sizeUpdated
: Date of last update to this file
psp_process
configuration (*.inp
)¶
The input deck file was designed to coordinate most of the inputs and
options needed for psp_process
. It is also a good reference for
which files influenced the final processed results. Descriptions of all
the variables included in the input deck are included in Table 1
@general
test = my-test-event-name
run = 1234
sequence = 56
tunnel = ames_unitary
@vars
dir = /nobackup/upsp/test_name
@all
sds = $dir/inputs/123456.wtd
grid = $dir/inputs/test-subject.grid
targets = $dir/inputs/test-subject.tgts
@camera
number = 1
cine = $dir/inputs/12345601.cine
calibration = $dir/inputs/cam01-to-model.json
aedc = false
@camera
number = 2
filename = $dir/inputs/12345602.mraw
calibration = $dir/inputs/cam02-to-model.json
aedc = false
@options
target_patcher = polynomial
registration = pixel
overlap = best_view
filter = gaussian
filter_size = 3
oblique_angle = 70
number_frames = 2000
@output
dir = $dir/outputs
Section |
Variable |
Description |
Required? |
How it is used |
---|---|---|---|---|
General |
||||
test |
test id number |
yes |
included in output HDF5 files |
|
run |
run number |
yes |
included in output HDF5 files |
|
sequence |
sequence number |
yes |
included in output HDF5 files |
|
tunnel |
tunnel identifier |
yes |
used for determining which tunnel transformations and input files to expect,
only currently support |
|
Vars |
allows variables to be set for use within the file |
no |
any variable can be used anywhere else in the file when preceeded with |
|
All |
||||
sds |
wind tunnel data (WTD) file |
yes |
many variables are included in the output HDF5 files; used to determine the orientation of the model for calibration; used as part of converting camera intensity to pressure |
|
grid |
grid file |
yes |
will be the basis of the projection from the image plane into space, data will be stored, when available, at each grid node |
|
targets |
targets file |
yes |
targets used to correct the calibration for this data point; targets and fiducials: patched over by the target patcher |
|
normals |
grid vertex normals override |
no |
allows for individually setting the normal direction for individual grid nodes, used as part of projection, useful for non-watertight structured grids |
|
Camera |
need a block per camera that will be processed |
|||
number |
camera id number |
yes |
used to match cine files to the correct camera calibration, should not have duplicate camera numbers |
|
cine |
cine file |
yes |
path to the camera video file that will be processed (deprecated; prefer “filename” key instead) |
|
aedc |
aedc cine file type flag |
no |
aedc format is different than other cine file formats, so it is used to read the cine file; default is false |
|
filename |
video file |
yes |
path to the
camera video file. Supported extensions: *.mraw, *.cine. For
*.mraw, the *.cih header file must be a sibling file of the *.mraw
file with the same basename, e.g., |
|
calibration |
model-to-camera external calibration file |
yes |
path to external
camera calibration file (output from |
|
Options |
||||
target_patcher |
type of target patching |
no |
decide what type of target patching is implemented, supports either |
|
registration |
image registration type |
no |
decide what type of image registration to perform, supports either |
|
overlap |
multi-view handling |
no |
specify how to handle points that are visible from multiple cameras, supports either
|
|
filter |
image plane filtering |
no |
decide what type of filtering to apply to each image prior to projection, supports
either |
|
filter_size |
size of the filter |
yes |
decide how large the filter will be in pixels, must be odd |
|
oblique_angle |
minimum projection angle |
no |
minimum angle between grid surface plane and camera ray to be considered visible by the camera; default 70 (degrees) |
|
number_frames |
number of frames to process |
yes |
number of camera frames to process (-1 = all frames) |
|
Output |
||||
dir |
output directory |
yes |
destination directory for output files |
External camera calibration configuration parameters¶
The external calibration application requires a set of configuration parameters. These parameters are mainly static parameters related to the tunnel, model setup in the tunnel, or hyper parameters related to the external calibration process. This input is stored as a JSON with the following elements:
oblique_angle
: Oblique viewing angle for target visibility checkstunnel-cor_to_tgts_tvec
: Tunnel center of rotation to targets frame translation vectortunnel-cor_to_tgts_rmat
: Tunnel center of rotation to targets frame rotation matrixtunnel-cor_to_tunnel-origin_tvec
: Tunnel center of rotation to tunnel origin translation vectortunnel-cor_to_tunnel-origin_rmat
: Tunnel center of rotation to tunnel origin rotation matrixdot_blob_parameters
: Blob detection parameters to find sharpie targetsdot_pad
: Sharpie target padding distance for sub-pixel localizationkulite_pad
: Kulite target padding distance for sub-pixel localizationmax_dist
: Maximum matching distance between a wind-off target position and a detected targetmin_dist
: Minimum distance between two targets before they become too close and ambiguous
Optional:
Updated
: Date of last update to this file
Batch processing configuration¶
Datapoint index¶
Example:
{
"__meta__": {
"config_name": "<string: alias for this index file, e.g., 'default'>",
"test_name": "<string: alias for the wind tunnel test name, e.g., 'my-test-event-name'>"
}
"<string: unique datapoint ID number, e.g., '123456'>": {
"camera_tunnel_calibration_dir": "<string: directory containing camera-to-tunnel calibration files>",
"camera_video_dir": "<string: path to directory containing camera video files>",
"grid_file": "<string: path to 3D model grid file>",
"kulites_files_path": "<string: path to folder containing kulite *.slow, *.fast, *.info files>",
"normals_file": "<string (optional): path to grid normals override file>",
"paint_calibration_file": "<string: path to uPSP unsteady gain calibration file>",
"steady_psp_file": "<string: path to steady-state PSP PLOT3D function file>",
"targets_file": "<string: path to targets file containing registration targets and fiducials>",
"wtd_file": "<string: path to wind tunnel data file>"
}
}
Each input file is described in more detail in other sections of this chapter
In the case of
*.mraw
-formatted camera video files, it is assumed that the corresponding*.cih
video header file is a sibling of the*.mraw
file in the same folder, with the same name (e.g.,12345601.mraw
and12345601.cih
).
Processing pipeline configuration parameters¶
The processing parameters file is a single location for the user to specify parameter values for all applications in the processing pipeline.
The file is structured to allow the user to specify a set of default values as well as one or more “overlays” to customize parameter values for individual datapoints or for sets of datapoints that share common characteristics. Each overlay is applied to a datapoint based on whether one or more key-value pairs in its entry in the datapoint index (see Datapoint index) matches a series of regular expressions (specified using Python-format syntax, see here).
Example:
{
"__meta__": {
"name": "<string: alias for these parameter settings, e.g., 'default'>"
},
"processing": {
"defaults": {
"psp_process": {
"cutoff_x_max": 120,
"filter": "none",
"filter_size": 1,
"number_frames": 20,
"oblique_angle": 70,
"registration": "pixel",
"target_patcher": "polynomial"
},
"external-calibration": {
"Updated": "07/27/2021",
"dot_blob_parameters": [
["filterByColor", 1],
["filterByArea", 1],
["filterByCircularity", 1],
["filterByInertia", 1],
["filterByConvexity", 1],
["thresholdStep", 1],
["minThreshold", 13],
["maxThreshold", 40],
["minRepeatability", 4],
["minDistBetweenBlobs", 0],
["blobColor", 0],
["minArea", 4],
["maxArea", 24],
["minCircularity", 0.72],
["maxCircularity", 0.95],
["minInertiaRatio", 0.25],
["maxInertiaRatio", 1.01],
["minConvexity", 0.94],
["maxConvexity", 1.01]
],
"dot_pad": 4,
"image_dims": [512, 1024, 1],
"kulite_pad": 3,
"max_dist": 6,
"min_dist": 10,
"model_length": 87.1388,
"oblique_angle": 70,
"sensor_resolution": [800, 1280, 1],
"sensor_size": [0.8818898, 1.4110236],
"sting_offset": [-195.5125, 0, 0],
"tgts_transformation_rmat": [
[1, 0, 0],
[0, 1, 0],
[0, 0, 1]
],
"tgts_transformation_tvec": [-32.8612, 0, 0],
"tunnel-cor_to_tgts_tvec": [-195.5125, 0, 0]
}
},
"test-model-geometry-2": {
"external-calibration": {
"model_length": 123.456
}
},
"test-model-geometry-3": {
"external-calibration": {
"model_length": 150.456
}
},
"__overlays__": [
["defaults", {".*": ".*"}],
["test-model-geometry-2", {"grid_file": ".*test-model-geometry-2.*"}]
["test-model-geometry-3", {"grid_file": ".*test-model-geometry-3.*"}]
]
}
}
Each child of "processing"
NOT named __overlays__
specifies
some/all parameter values for some/all applications in the pipeline, and
is referred to here as a “parameter set”. Each parameter set is given a
name, for example, "defaults"
or "test-model-geometry-3"
in the above file.
Each parameter set need not specify every available application
parameter; in the example above, "defaults"
contains a full
specification, whereas "test-model-geometry-3"
contains a specific value just
to override the "model_length"
parameter of the "external-calibration"
pipeline application. The "test-model-geometry-3"
overlay is applied to all
datapoints whose "grid_file"
matches the regular expression r".*test-model-geometry-2.*"
In general, all parameter names map to corresponding parameters supplied directly to each pipeline application when running them individually/manually (see Pipeline Application Design Details).
The __overlays__
section specifies how to use the parameter sets to
configure each datapoint. The user must provide a list of overlay
entries, each in the format [<name>, <patterns>]
. Each datapoint
matching the contents of <patterns>
will use the parameter values
given by the parameter set named <name>
. Overlays are applied in the
order listed, so in the example above, the config123
parameter set
will override any values already specified in defaults
. The usage of
<patterns>
for matching a datapoint is as follows:
<patterns>
is a dictionary where each keyk
and each valuev
are regular expression strings (Python-format)For each entry in
<patterns>
, and for each input in the index JSON (grid_file
,targets_file
, etc.)If the input key matches the regular expression given by
k
, thenThe input value is tested against the regular expression given by
v
.
If all tests pass for all entries in
<patterns>
, then the datapoint “matches.”
Portable Batch Scheduler (PBS) job configuration parameters¶
Example:
{
"__meta__": {
"name": "<string: alias for these NAS settings, e.g., 'default'>"
},
"nas": {
"__defaults__": {
"charge_group": "<string: UNIX group id, e.g., 'g1234'>",
"node_model": "<string: NAS node mode, e.g., 'ivy'>",
"queue": "<string: NAS job queue name, e.g., 'normal'>",
"number_nodes": "<integer: number of NAS nodes for processing, e.g., 10>",
},
"external-calibration": {
"launcher": "parallel",
"wall_time": "<string: wall clock time to run this step, per data point, e.g., '00:10:00'>"
},
"extract-first-frame": {
"launcher": "parallel",
"wall_time": "<string: wall clock time to run this step, per data point, e.g., '00:10:00'>"
},
"psp_process": {
"launcher": "serial",
"number_nodes": "<integer: number of NAS nodes for processing, e.g., 40>",
"wall_time": "<string: wall clock time to run this step, per data point, e.g., '00:10:00'>"
},
"render-images": {
"launcher": "parallel",
"wall_time": "<string: wall clock time to run this step, per data point, e.g., '00:10:00'>"
}
}
}
Each step in the pipeline should be assigned a full set of NAS job
parameters. A set of __defaults__
will apply to all steps, and then
optional overrides can be provided in a section named for each step. The
job parameters are used by qsub-step
to launch step jobs on the NAS
cluster nodes, and are tuned primarily by the number of vertices in the
grid file and the number of frames in each camera video file. See
Guidelines for setting NAS PBS job parameters for more details.
Plotting configuration parameters¶
Example:
{
"__meta__": {
"name": "<string: alias for these plotting settings, e.g., 'default'>"
},
"plotting": {
"render-images": {
"scalars": {
"steady_state": {
"display_name": "Steady State",
"contours": [-1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0]
},
"rms": {
"display_name": "delta Cp RMS",
"contours": [0, 0.005, 0.01, 0.015, 0.02, 0.025, 0.03]
}
},
"grids": {
"config111": {
"views": {
"left-side": {
"x": 123.4,
"y": 123.4,
"z": 123.4,
"psi": 90.0,
"theta": 0.0,
"width": 120.0,
"imagewidth": 1280
},
},
"exclude_zones": [101, 120]
}
}
},
"generate-miniwall": {
"variables": [
{"name": "mach", "format": "%4.3f", "values": [0.8, 0.85, 0.9]},
{"name": "alpha", "format": "%4.2f", "values": [0.0, 5.0, 10.0]},
{"name": "beta", "format": "%4.2f", "values": [0.0, 5.0, 10.0]}
],
"selectors": ["alpha", "beta"],
"layout": {"cols": ["mach"], "rows": ["alpha", "beta"]},
"site": {
"page_name": "My MiniWall",
"images_dir": "images",
"model_config_prefix": "PREFIX"
},
"run_log": {
"model_config": "111",
"path": "my-run-log.txt"
},
"image_discovery": {
"ext": "png",
"patterns": {
"datapoint": "[0-9]{6}",
"panel_name": "[0-9][0-9]"
},
"cache": "lib/image_discovery.json"
}
}
}
}
All parameters map to corresponding elements of the upsp-plotting
configuration file (see Pipeline Application Design Details).
Output files from psp_process
¶
Output data from psp_process
consists of \(\Delta C_p\)
measurements versus time for all nodes of the user-provided wind tunnel
model grid. The measurements are provided either in raw binary format or
bundled into an HDF5 file. In addition, metadata containing the model
grid definition, wind tunnel conditions, and camera settings are bundled
with the measurements in the HDF5 file.
Pressure-time history raw binary outputs¶
The psp_process
application will produce two (often large) binary
files called pressure
and pressure_transpose
. If using the batch
processing tools (described in Batch processing configuration),
these files will be available in the output/10_other/additional_output
subdirectory
for each datapoint; otherwise, they will be available in the directory
supplied to psp_process
using the --add_out_dir
command line
option. Both files contain the same data, however, the formatting
differs to facilitate downstream use cases.
The pressure
binary file is formatted as follows. For a given
datapoint, the primary output data from psp_process
is the
pressure-time history, defined as a matrix \(P\) of size
\([N_f \times N_m]\) where \(N_f\) is the number of frames from
a uPSP camera (all cameras are synchronized, so this corresponds to the
number of time steps) and \(N_m\) is the number of grid nodes. If we
let \(i = 1, 2, \ldots, N_f\), and \(j = 1, 2, \ldots, N_m\),
then element \(P_{i, j}\) corresponds to the unsteady pressure
(\(\Delta C_p\)) measured during the \(i\)’th time step at the
location of the \(j\)’th model grid node (the ordering of grid
nodes corresponds one-to-one with the ordering in the user-supplied
model grid definition file; see Surface grid definition).
Equivalently, rows of \(P\) correspond to snapshots of the pressure
distribution over the entire grid at each time step. The pressure
binary file contains the matrix \(P\) written to disk in row-major
format, where each value is a 32-bit, little endian, IEEE floating point
number. This corresponds to the following sequence of matrix elements:
Because this file can be quite large (for example, a grid with 1 million
nodes and a datapoint with 50,000 time points will have a total of 50
billion floating point values, corresponding to approximately 186 GB),
performance of file read operations can become an issue during
post-processing. It is advantageous to read contiguous values from the
file, meaning the pressure
binary file is best suited for analyses
of the entire model grid for a subset of time history.
To facilitate analyses of the entire time history for a subset of
model grid nodes, a separate pressure_transpose
file is also
generated. It contains the values of the transpose of \(P\)
written to disk in a similar row-major format. This corresponds to the
following sequence of matrix elements:
In the pressure_transpose
file, the time history for each individual
grid node is contiguous in memory.
The following Python code snippet demonstrates how the
pressure_transpose
flat file may be used to obtain the time history
for a single model grid node:
import numpy as np
import os
def read_pressure_transpose(filename, number_grid_nodes, node_index):
""" Returns a 1-D numpy array containing model grid node pressure time history
- filename: path to pressure_transpose file
- number_grid_nodes: total number of model grid nodes
- node_index: index of grid node (zero-based) in model grid file
"""
filesize_bytes = os.path.getsize(filename)
itemsize_bytes = 4 # 32-bit floating point values
number_frames = int((filesize_bytes / itemsize_bytes) / number_grid_nodes)
assert(number_frames * number_grid_nodes * itemsize_bytes == filesize_bytes)
with open(filename, 'rb') as fp:
offset = node_index * number_frames
fp.seek(offset, 0)
return np.fromfile(fp, dtype=np.float32, count=number_frames)
HDF5-formatted files¶
HDF5-formatted files are also provided containing the pressure-time history solution matrix and associated metadata.
Diagnostics and quality checks¶
There are a number of additional outputs that are useful for checking
behavior of the processing code and to check quality of input data
files. By default, outputs are stored in the output directory specified
in the input deck file; this can be overridden using the
-add_out_dir
command line option. Table 2
describes each output file in more detail.
File name |
Description |
---|---|
|
first frame, scaled to 8-bit |
|
first frame, converted to high-dynamic-range, 32-bit, OpenEXR format. High-fidelity representation of the first frame from the camera. Pixel values are equal to those in the source image — all supported source video files have less than 32 bits per pixel, so 32-bit OpenEXR provides a way to preserve fidelity across vendor-specific input video files. |
|
first frame, scaled to 8-bit, with fiducial positions from the |
|
first frame, scaled to 8-bit, with fiducials colored according to their cluster ID (only clusters with >1 fiducial are assigned colors) |
|
first frame, scaled to 8-bit, showing boundaries drawn around fiducial clusters. Pixels inside the drawn boundaries will be “patched” by replacing their values with a polynomial interpolant (prior to projection to the 3D grid) |
|
first frame, colormapped to show # grid nodes mapped to each pixel. Ideally, if no image filter is used, then there should be an approximate one-to-one map of grid nodes to pixel; otherwise, an image filter can be used to average neighboring pixels, so that pixels with no grid node will have their value averaged into a neighboring value that does map to a grid node. If there are many more grid nodes than pixels, then it may indicate the grid resolution is over-specified compared to the resolution of the camera. |