retinafilt.C
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include "Image/Image.H"
00039 #include "Image/ImageSet.H"
00040 #include "Image/Pixels.H"
00041 #include "Image/PyramidOps.H"
00042 #include "Raster/Raster.H"
00043
00044 #include <algorithm>
00045 #include <cmath>
00046 #include <cstdio>
00047 #include <typeinfo>
00048
00049
00050 #define PYR_DEPTH 10
00051
00052
00053 #define BLIND_X 0.15f
00054 #define BLIND_Y 0.00f
00055
00056
00057 #define BLIND_2S2 600.0f
00058
00059
00060 #define FOVEA_2S2 150.0f
00061
00062
00063 template <class T>
00064 void showtypeof(T t, const char* expr)
00065 {
00066 LINFO("type of %s is %s", expr, typeid(T).name());
00067 }
00068
00069 #define SHOWTYPEOF(x) showtypeof(x, #x)
00070
00071
00072 int main(int argc, char **argv)
00073 {
00074 bool fovea_blue = false, blind_spot = false;
00075 if (argc < 3) {
00076 fprintf(stderr,
00077 "USAGE: %s [opts] <input.ppm> <output.ppm> [fov_x fov_y]\n"
00078 "options:\n"
00079 " -b implement blind spot\n"
00080 " -f no blue cones in fovea\n", argv[0]);
00081 exit(1);
00082 }
00083 int ar = 1;
00084 if (argv[ar][0] == '-') {
00085 for (unsigned int ii = 1; ii < strlen(argv[ar]); ii ++) {
00086 switch (argv[ar][ii]) {
00087 case 'b': blind_spot = true; break;
00088 case 'f': fovea_blue = true; break;
00089 default: LFATAL("Unknown option '%c'.", argv[ar][ii]);
00090 }
00091 }
00092 ar ++;
00093 }
00094
00095
00096 Image< PixRGB<byte> > input = Raster::ReadRGB(argv[ar++]);
00097
00098
00099 ImageSet< PixRGB<byte> > pyr = buildPyrGaussian(input, 0, PYR_DEPTH, 5);
00100
00101
00102 int w = input.getWidth(), h = input.getHeight(), ci = w / 2, cj = h / 2;
00103
00104
00105 if (argc - ar > 1)
00106 {
00107 ci = atoi(argv[ar + 1]); ci = std::max(0, std::min(w-1, ci));
00108 cj = atoi(argv[ar + 2]); cj = std::max(0, std::min(h-1, cj));
00109 LINFO("Using (%d, %d) for fovea center", ci, cj);
00110 }
00111
00112 Image< PixRGB<byte> > output(w, h, NO_INIT);
00113 float rstep = float(std::max(w, h) / PYR_DEPTH);
00114 int bi = ci + int(w * BLIND_X), bj = cj + int(h * BLIND_Y);
00115
00116 for (int i = 0; i < w; i ++)
00117 for (int j = 0; j < h; j ++)
00118 {
00119 float dist = sqrtf((i-ci)*(i-ci) + (j-cj)*(j-cj));
00120
00121
00122 float d = dist / rstep;
00123
00124
00125 int di = int(d);
00126 float dd = d - float(di);
00127
00128
00129
00130
00131
00132 Point2D<int> loc(i, j);
00133 PixRGB<byte> pix0 = getPyrPixel(pyr, loc, di);
00134 PixRGB<byte> pix1 = getPyrPixel(pyr, loc, std::min(di+1, PYR_DEPTH-1));
00135
00136 float blind = 1.0f;
00137 if (blind_spot)
00138 blind = 1.0f - expf(-((i-bi)*(i-bi) + (j-bj)*(j-bj)) / BLIND_2S2);
00139
00140 static bool didit = false;
00141
00142 if (!didit)
00143 {
00144 SHOWTYPEOF(pix0);
00145 SHOWTYPEOF(pix1);
00146 SHOWTYPEOF(pix1-pix0);
00147 SHOWTYPEOF((pix1-pix0)*dd);
00148 SHOWTYPEOF(pix0 + (pix1-pix0)*dd);
00149 SHOWTYPEOF((pix0 + (pix1-pix0)*dd) * blind);
00150 didit = true;
00151 }
00152
00153 PixRGB<byte> pix( (pix0 + (pix1 - pix0) * dd) * blind );
00154 if (fovea_blue)
00155 pix.setBlue(pix.blue() * (1.0f - expf(-dist * dist / FOVEA_2S2)));
00156
00157
00158
00159
00160
00161
00162
00163 output.setVal(loc, pix);
00164 }
00165
00166
00167 Raster::WriteRGB(output, argv[ar], RASFMT_PNM);
00168 return 0;
00169 }
00170
00171
00172
00173
00174
00175
00176