Skip to content

Commit

Permalink
Merge branch 'dev'
Browse files Browse the repository at this point in the history
  • Loading branch information
wandell committed Apr 17, 2024
2 parents b147120 + 5653c65 commit d971044
Show file tree
Hide file tree
Showing 48 changed files with 1,447 additions and 368 deletions.
Binary file added data/sensor/colorfilters/auto/SONY/cf_imx490.mat
Binary file not shown.
Binary file modified data/sensor/colorfilters/auto/SONY/qe_imx490.mat
Binary file not shown.
Binary file not shown.
41 changes: 41 additions & 0 deletions data/sensor/colorfilters/auto/SONY/s_imx490QEdata.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
%% Managing the IMX490 spectral QE
%
% Grabit on the scanned image in sonyIMX490.png produced the first
% file.

%%
datadir = fullfile(isetRootPath,'data','sensor','colorfilters','auto','SONY');
curdir = pwd;
chdir(datadir);

%% Data from grabit, via Zhenyi
tmp = load('qe_imx490_scan.mat');

% Scale to 0,1
tmp.data = tmp.data/100;

tmp.data(tmp.data<0) = 0;
tmp.data(isnan(tmp.data)) = 0;

ieNewGraphWin; plot(tmp.wavelength,tmp.data);
xaxisLine;

%% Write it out in the two formats. Not sure why we have two.

%% CF file
tmp.filterNames = {'r','g','b'};
tmp.comment = 'Cleaned up QE from grabit scan of LUCID curves.';

cfFile = fullfile(datadir,'cf_imx490.mat');

ieSaveColorFilter(tmp,cfFile);
disp("Saved Sony imx490 spectral qe as a color filter.")
disp('Read it using ieReadColorFilter')

%% QE file
qeFile = fullfile(datadir,'qe_imx490.mat');
ieSaveSpectralFile(tmp.wavelength,tmp.data,tmp.comment,qeFile);
disp("Saved Sony imx490 spectral qe as a color filter.")
disp('Read it using ieReadSpectra.')

%%
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
File renamed without changes.
8 changes: 7 additions & 1 deletion imgproc/demosaic/Demosaic.m
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,8 @@
switch lower(m)
case {'iebilinear','bilinear'}
method = 'ieBilinear';
case {'matlabbilinear'}
method = 'matlabbilinear';
case {'multichannel'}
method = 'multichannel';
case {'adaptivelaplacian'}
Expand Down Expand Up @@ -174,7 +176,11 @@
% Rarely go this computational path. Mainly used for human retina.
demosaicedImage = demosaicMultichannel(imgRGB,sensor,'interpolate');
end

case {'matlabbilinear'}
% [1] Malvar, H.S., L. He, and R. Cutler, High quality linear
% interpolation for demosaicing of Bayer-patterned color
% images. ICASPP, Volume 34, Issue 11, pp. 2274-2282, May 2004.
demosaicedImage = demosaic(imgRGB,sensorGet(sensor,'pattern'));
case 'adaptivelaplacian'
clipToRange = 0;
if (strcmp(bPattern,'grbg') || ...
Expand Down
42 changes: 30 additions & 12 deletions metrics/scielab/scPrepareFilters.m
Original file line number Diff line number Diff line change
Expand Up @@ -33,18 +33,7 @@
% The filters are a cell array. The support defines the spatial support in
% terms of degrees of visual angle.
%
% Example:
% params.deltaEversion = '2000';
% params.sampPerDeg = 145;
% params.imageFormat = 'LMS';
% params.filterSize = 145;
% params.dimension = 2;
% [filters,support] = scPrepareFilters(params);
%
% figure; % Units are degrees of visual angle
% subplot(1,3,1), mesh(support,support,filters{1}); colormap(hsv(256));
% subplot(1,3,2), mesh(support,support,filters{2}); colormap(hsv(256));
% subplot(1,3,3), mesh(support,support,filters{3}); colormap(hsv(256));
% The source code below contains a runnable example.
%
% In 1996, Xuemei Zhang used this routine
% [k1, k2, k3] = separableFilters(params.sampPerDeg,2);
Expand All @@ -59,6 +48,35 @@
%
% Copyright ImagEval Consultants, LLC, 2003.

% Examples:
%{
clear; close all;
params.deltaEversion = '2000';
params.sampPerDeg = 145;
params.imageFormat = 'LMS';
params.filterSize = 145;
params.dimension = 2;
[filters,support] = scPrepareFilters(params);
% Units are degrees of visual angle
figure; clf;
subplot(1,3,1), mesh(support,support,filters{1}); colormap(hsv(256));
subplot(1,3,2), mesh(support,support,filters{2}); colormap(hsv(256));
subplot(1,3,3), mesh(support,support,filters{3}); colormap(hsv(256));
% In 1996, Xuemei Zhang used this routine
[k1, k2, k3] = separableFilters(params.sampPerDeg,2);
figure; clf;
subplot(1,2,1); mesh(support,support,filters{3})
subplot(1,2,2); mesh(support,support,k1)
% The values are the same aes shown by the zero difference
figure; clf;
subplot(1,3,1); mesh(support,support,k1-filters{1});
subplot(1,3,2); mesh(support,support,k2-filters{2});
subplot(1,3,3); mesh(support,support,k3-filters{3});
%}

% Check parameters
if ieNotDefined('params'), error('Params required.'); end
if ~checkfields(params,'sampPerDeg'), params.sampPerDeg = 224; end
Expand Down
41 changes: 26 additions & 15 deletions opticalimage/oiCompute.m
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@
%
% crop - Crop the OI to the same size as the scene. (Logical)
% Default: false;
% (We could do a setprefs on these, but BW is resistant.)
%
% pixel size - Spatial resolution of the oi image. A scalar in
% meters. Normally it is set to match the optics and
% scene properties.
%
% Return
% oi - The oi with computed photon irradiance
Expand Down Expand Up @@ -57,12 +60,12 @@
% in opticsDLCompute. This blur and intensity in this computation depends
% on the diffraction limited parameters (f/#) but little else.
%
% To create an image with no blur, set the f/# to a very small number.
% This will provide an image that has the geometry and zero-blur as used in
% computer graphics pinhole cameras. The absolute light level, however,
% will be higher than what would be seen through a small pinhole. You can
% manage this by setting scaling the spectral irradiance
% (oiAdjustIlluminance).
% To create an image with no blur, set the f/# (focal length over the
% aperture) to be a very small number. This image has the geometry and
% zero-blur as used in computer graphics pinhole cameras. The
% absolute light level, however, will be higher than what would be
% seen through a small pinhole. You can manage this by setting scaling
% the spectral irradiance (oiAdjustIlluminance).
%
% * The second model is shift-invariant optics. This depends on having a
% wavelength-dependent OTF defined and included in the optics structure.
Expand Down Expand Up @@ -123,6 +126,13 @@
oi = oiCompute(oi,scene,'pad value','border','crop',true);
oiWindow(oi);
%}
%{
% Almost right. Off by 1 part in 100. Need to fix. (BW).
scene = sceneCreate;
oi = oiCreate;
oi = oiCompute(oi,scene,'pad value','border','crop',true,'pixel size',1e-6);
oiWindow(oi);
%}
%% Parse
varargin = ieParamFormat(varargin);
p = inputParser;
Expand All @@ -135,28 +145,29 @@
p.parse(oi,scene,varargin{:});

% Ages ago, we some code flipped the order of scene and oi. We think
% we have caught all those cases, but we still test. Maybe delete
% this code by January 2024.
% we have caught all those cases, but we still test, and are now forcing
% the user to correct.
if strcmp(oi.type,'scene') && (strcmp(scene.type,'opticalimage') ||...
strcmp(scene.type,'wvf'))
warning('flipping oi and scene variables.')
tmp = scene; scene = oi; oi = tmp; clear tmp
error('You need to flip order oi and scene variables in the call to oiCompute')
% We used to help the user
% tmp = scene; scene = oi; oi = tmp; clear tmp
end
%% Adjust oi fov if user send in a pixel size

%% Adjust oi fov if user sends in a pixel size
if ~isempty(p.Results.pixelsize)
pz = p.Results.pixelsize;
sw = sceneGet(scene, 'cols');
flengthM = oiGet(oi, 'focal length', 'm');
wAngular = atand(pz*sw/2/flengthM)*2;
% oi use scene hFOV later.
% oi uses scene hFOV later.
scene = sceneSet(scene, 'wAngular',wAngular);
end

%% Compute according to the selected model.

%
% Should we pad the scene before the call to these computes?

%
% We pass varargin because it may contain the key/val parameters
% such as pad value and crop. But we only use pad value here.
if strcmp(oi.type,'wvf')
Expand Down
68 changes: 44 additions & 24 deletions opticalimage/oiCreate.m
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
%
% Inputs
% oiType -
% {'pinhole'} - Turn off cos4th, infinite depth of field and
% NaN focal length
%
% {'diffraction limited'} - Diffraction limited optics, no diffuser or
% data (Default). Equivalent to using the wvf or
% shift-invariant with a zero wavefront
Expand Down Expand Up @@ -103,15 +106,6 @@
%%
scene = []; wvf = [];
switch ieParamFormat(oiType)
case {'empty'}
% Just the basic shell of the oi struct
% Other terms will get added by the calling function
oi.type = 'opticalimage';
oi.name = vcNewObjectName('opticalimage');
oi.metadata = []; % Store metadata typically for machine-learning apps
oi = oiSet(oi, 'diffuser method', 'skip');
oi = oiSet(oi,'wave',[]);

case {'diffractionlimited','default'}
% Diffraction limited is implemented using the dlMTF method.
% This is like the wvf case, but the dl MTF is computed on the fly
Expand All @@ -136,6 +130,47 @@
oi.optics.transmittance.scale = ones(length(370:730), 1);
end

case {'pinhole'}
% Pinhole optics in an OI.
%
% We set the f/# (focal length over the aperture) to be a very
% small number. This image has zero-blur because the
% diffraction aperture is very large. That is the goal of the
% pinhole camera optics, but the way we achieve it is odd.
%
% The absolute light level is high because a small fnumber
% means the focal length is very short compared to the
% aperture.
%
% With these default settings the focal length is 10 mm and the
% aperture diameter is 10 m.
oi = oiCreate();
oi = oiSet(oi, 'name', 'pinhole');
oi = oiSet(oi, 'optics name','pinhole');

% This makes the computation a pinhole
oi = oiSet(oi,'optics model','skip');
oi = oiSet(oi, 'optics offaxis method', 'skip');
oi = oiSet(oi, 'diffuser method', 'skip');

% Not sure why we set these, but it is true that when we have
% a very small fnumber, we should have no blur - like a
% pinhole.
oi = oiSet(oi, 'optics fnumber',1e-3);
oi = oiSet(oi, 'optics focal length',1e-2);

% Pinhole do not have a focal length or fNumber.
wvf = [];

case {'empty'}
% Just the basic shell of the oi struct
% Other terms will get added by the calling function
oi.type = 'opticalimage';
oi.name = vcNewObjectName('opticalimage');
oi.metadata = []; % Store metadata typically for machine-learning apps
oi = oiSet(oi, 'diffuser method', 'skip');
oi = oiSet(oi,'wave',[]);

case {'shiftinvariant','wvf'}
% We create via the wavefront method. We create a wvf, convert it
% to an oi using wvf2oi, which calls wvf2optics.
Expand Down Expand Up @@ -277,21 +312,6 @@
oi = oiSet(oi,'fov',100);
wvf = [];

case {'pinhole'}
% Pinhole camera version of OI
oi = oiCreate('shift invariant');
oi = oiSet(oi, 'optics model', 'skip');
oi = oiSet(oi, 'bit depth', 64); % Forces double
oi = oiSet(oi, 'optics offaxis method', 'skip');
oi = oiSet(oi, 'diffuser method', 'skip');

% Pinhole do not have a focal length. In this case, the focal
% length is used to say the image plane distance.
oi = oiSet(oi, 'optics focal length',NaN);
oi = oiSet(oi, 'optics name','pinhole');
oi = oiSet(oi, 'name', 'pinhole');
wvf = [];

otherwise
fprintf('\n--- Valid OI types: ---\n')
for ii=1:length(validTypes)
Expand Down
14 changes: 9 additions & 5 deletions opticalimage/oiGet.m
Original file line number Diff line number Diff line change
Expand Up @@ -404,10 +404,12 @@
if ~isempty(varargin), val = val*ieUnitScaleFactor(varargin{1}); end

case {'wangular','widthangular','hfov','horizontalfieldofview','fov'}
% oiCompute(oi,scene) assigns the angular field of view to the oi.
% oiCompute(oi,scene) assigns the angular field of
% view to the oi.
%
% This horizontal FOV represents the size of the OI,
% usually after the computational padding.
% reflects the angle of the scene it represents.
% usually after the computational padding. Reflects
% the angle of the scene it represents.
if checkfields(oi,'wAngular')
val = oi.wAngular;
else
Expand All @@ -416,10 +418,12 @@
% 'focal plane distance'.
fprintf('*** The oi fov is not set yet. ');
scene = vcGetObject('scene');
if isempty(scene) % Default scene visual angle.
if isempty(scene)
% Default scene visual angle.
fprintf('Using a default fov of 10.\n');
disp('oiGet: No scene, arbitrary oi angle: 10 deg'), val = 10;
else % Use current scene angular width
else
% Use current scene angular width
fprintf('Using the scene fov.\n');
val = sceneGet(scene,'wangular');
end
Expand Down
Loading

0 comments on commit d971044

Please sign in to comment.