/usr/share/psychtoolbox-3/PsychGLImageProcessing/DisplayUndistortionCSV.m is in psychtoolbox-3-common 3.0.11.20131230.dfsg1-1build1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 | function scal = DisplayUndistortionCSV(calibinfilename, caliboutfilename, screenid)
% scal = DisplayUndistortionCSV(calibinfilename [, caliboutfilename][, screenid])
%
% Geometric display calibration procedure for undistortion of distorted
% displays. Needs graphics hardware with basic support for the PTB imaging
% pipeline (see below).
%
% Many display devices, e.g., video beamers and most CRT displays cause
% some amount of spatial distortion to your visual stimuli during display.
% Video projection onto curved screens will cause an especially large
% amount of distortion.
%
% Psychtoolbox can "undistort" your visual stimuli for you: At stimulus
% onset time, PTB applies a geometric warping transformation to your
% stimulus which is meant to counteract or cancel out the geometric
% distortion caused by your display device. If both, PTB's warp transform
% and the implicit distortion transform of the display match, your stimulus
% will show up undistorted on the display device.
%
% For this to work, PTB needs two things:
%
% 1. Recent graphics hardware with support for the PTB imaging pipeline:
% See our Wiki for recommendations. However, all ATI cards starting with
% Radeon 9500 and all NVidia cards of type GeForce-FX5200 and later, as
% well as the Intel-GMA 950 and later should be able to do it, although
% more recent cards will have a higher performance.
%
% 2. A calibration file that defines the warp transformation to apply. Your
% experiment script will load that file into Screen's "warp engine" at the
% beginning of your experiment and Screen() will automatically apply that
% warping to each stimulus image before output.
%
% DisplayUndistortionCSV defines a continous mapping (x', y') = f(x, y)
% from uncorrected input pixel locations (x,y) in your stimulus image to
% output locations (x', y') on your display. This mapping is defined by a
% linear mesh of quadrilaterals, as read from the given input file. The
% file format is compatible with the Warp-API of NVidia's proprietary
% graphics drivers for some high-end Quadro GPUs on Windows-7 and later.
%
%
% How to use:
% -----------
%
%
% Execute the function with the following parameters:
%
%
% `calibinfilename` is the path and filename of an existing calibration
% file. This must be a ASCII file with a one-line header, describing the
% meaning of the data columns, followed by at least 4 lines with numeric
% calibration data. Each line defines a data row, which has six columns,
% delimited with a semicolon ';'. The columns of a row have the following
% meaning: vx;vy;tx;ty;c;r
%
% vx = Output mesh vertex x position.
% vy = Output mesh vertex y position.
% tx = Input framebuffer corresponding x position.
% ty = Input framebuffer corresponding y position.
% c = Column index of the vertex.
% r = Row index of the vertex.
%
% Each row describes one vertex of a mesh of connected quadrilaterals
% (GL_QUADS). The mesh is basically a rectilinear grid, whose "grid line"
% intersections are the locations of the vertices. The mesh gets distorted
% by moving around those intersections, thereby forming the actual warp
% mesh.
%
% Pixel color values at location (tx,ty) of the input framebuffer are
% projected to location (vx,vy) of the warped output framebuffer. Quads are
% defined by 4 vertices which define their corners. Pixel sampling and
% output locations inside quads are bilinearly interpolated for a smooth
% warp grid. The origin of the calibration coordinate system is the
% top-left framebuffer / screen corner (0,0), x-axis points to the right,
% y-axis points downwards. All coordinates are normalized to a unit square
% screen. The range 0.0 - 1.0 maps to the screen width or height (0.0 =
% Left or Top, 1.0 = Right or bottom) and is subject to rescaling for a
% specific displays real resolution. Values outside the 0-1 range are
% allowed. The corresponding mesh locations will be clipped to screen
% corners during warping.
%
% The file format described here is the format expected by NVidia's
% Warp-API, as implemented in some binary NVidia graphics drivers for some
% high-end Quadro graphics cards on Windows-7 and later. This allows to
% reuse the file for both NVidia proprietary distortion correction and for
% Psychtoolbox.
%
%
% `caliboutfilename` Name of the file to which calibration results should
% be stored. If no name is provided, the file will be stored inside the
% 'GeometryCalibration' subfolder of your psychtoolbox configuration
% directory (path is PsychToolboxConfigDir('GeometryCalibration'). The
% filename will contain the screenid of the display that was calibrated.
%
%
% `screenid` screen id of the target display for calibration. The parameter
% is optional, defaults to zero, and is only used to generate the default
% filename for the output file.
%
%
% This script will print out a little snippet of code that you can paste
% and include into your experiment script - That will automatically load
% the calibration result file and apply the proper undistortion operation.
%
% History:
%
% 07/27/12 Written (MK).
% Child protection:
AssertOpenGL;
if ~exist('screenid', 'var') || isempty(screenid)
screenid = 0;
end
if ~exist('calibinfilename', 'var') || isempty(calibinfilename) || ~ischar(calibinfilename)
error('You must provide the namestring of a valid calibration input file as parameter "calibinfilename"!');
end
% Check for such a file:
if ~exist(calibinfilename, 'file')
error('Calibration input file %s does not exist or is inaccessible!', calibinfilename);
end
% Ok, valid file provided. Read it in:
try
% Parse ASCII text file. First line is header - skip it, start at row
% index 1 instead. Start with first column (0). Delimiter is a
% semicolon. Matrix m contains all values:
m = dlmread(calibinfilename, ';', 1, 0);
catch %#ok<*CTCH>
error('Failed to load input calibration file %s for some reason.', calibinfilename);
end
fprintf('\nLoaded calibration data from ASCII file %s.\n', calibinfilename);
% At this point, screenid contains the final screenid for the screen to
% calibrate. Assign it to scal struct. This will create 'scal' if it
% doesn't exist yet, or override its screenid in some cases:
scal.screenNumber = screenid;
% Define type of mapping for this calibration method: This is used in the
% CreateDisplayWarp() routine when parsing the calibration file to detect
% the type of undistortion method to use, ie. how to interpret the data in
% the calibration file to setup the calibration.
warptype = 'CSVDisplayList'; %#ok<NASGU>
n = size(m, 1);
if n < 4 || size(m, 2) ~= 6
error('ASCII input file must have at least 4 rows with six columns of data in each row, to define at least one quadrilateral.')
end
% Find number of vertex rows and columns for calibration mesh:
cols = max(m(:, 5)) + 1; % Column indices are zero-based, so add 1 for real count.
rows = max(m(:, 6)) + 1; % Row indices are zero-based, so add 1 for real count.
if n ~= (cols * rows)
error('Mismatch between number of data lines in file and maximum row and column indices in ASCII file! File corrupt?!?');
end
% Build 2D matrices: rows x cols per plane, 2 planes for x and y
% components:
% Vertex coordinates of the rendered output meshes quad vertices:
scal.vcoords = zeros(rows, cols, 2);
% Corresponding texture coordinates for sourcing from input framebuffer:
scal.tcoords = zeros(rows, cols, 2);
% Parse the 'm' matrix and fill scal.vcoords and scal.tcoords:
for i = 1:n
tc = m(i, 5) + 1; % Target column in matrices.
tr = m(i, 6) + 1; % Target row in matrices.
scal.vcoords(tr, tc, 1) = m(i, 1); % vertex x.
scal.vcoords(tr, tc, 2) = m(i, 2); % vertex y.
scal.tcoords(tr, tc, 1) = m(i, 3); % texture x [u].
scal.tcoords(tr, tc, 2) = m(i, 4); % vertex y [v].
end
% 'scal' contains the final results of calibration. Write it out to
% calibfile for later use by the runtime routines:
% Check if name for calibration result file is provided:
if ~exist('caliboutfilename', 'var')
caliboutfilename = [];
end
if isempty(caliboutfilename)
% Nope: Assign default name - Store in dedicated subfolder of users PTB
% config dir, with a well defined name that also encodes the screenid
% and resolution for which to calibrate:
caliboutfilename = [ PsychtoolboxConfigDir('GeometryCalibration') 'CSVCalibdata' sprintf('_%i', screenid) '.mat'];
fprintf('\nNo name for calibration file provided. Using default name and location...\n');
end
% Print name of calibfile and check for existence of file:
fprintf('Name of calibration result file: %s\n\n', caliboutfilename);
if exist(caliboutfilename, 'file')
answer = input('This file already exists. Overwrite it [y/n]? ','s');
if ~strcmpi(answer, 'y')
fprintf('\n\nCalibration aborted. Please choose a different name for calibration result file.\n\n');
return;
end
end
% Save all relevant calibration variables to file 'caliboutfilename'. This
% method should work on both, Matlab 6.x, 7.x, ... and GNU/Octave - create
% files that are readable by all runtime environments:
save(caliboutfilename, 'warptype', 'scal', '-mat', '-V6');
fprintf('Import of Calibration file finished :-)\n\n');
fprintf('You can apply the calibration in your experiment script by replacing your \n')
fprintf('win = Screen(''OpenWindow'', ...); command by the following sequence of \n');
fprintf('commands:\n\n');
fprintf('PsychImaging(''PrepareConfiguration'');\n');
fprintf('PsychImaging(''AddTask'', ''LeftView'', ''GeometryCorrection'', ''%s'');\n', caliboutfilename);
fprintf('win = PsychImaging(''OpenWindow'', ...);\n\n');
fprintf('This would apply the calibration to the left-eye display of a stereo setup.\n');
fprintf('Additional options would be ''RightView'' for the right-eye display of a stereo setup,\n');
fprintf('or ''AllViews'' for both views of a stereo setup or the single display of a mono\n');
fprintf('setup.\n\n');
fprintf('The ''GeometryCorrection'' call has a ''debug'' flag as an additional optional parameter.\n');
fprintf('Set it to a non-zero value for diagnostic output at runtime.\n');
fprintf('E.g., PsychImaging(''AddTask'', ''LeftView'', ''GeometryCorrection'', ''%s'', 1);\n', caliboutfilename);
fprintf('would provide some debug output when actually using the calibration at runtime.\n\n\n');
% Done.
return;
|