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 #include "SpaceVariant/ScaleSpaceOps.H"
00037 #include "Image/ImageSet.H"
00038 #include "Image/Pixels.H"
00039 #include "Image/LowPass.H"
00040 #include "Util/Assert.H"
00041
00042
00043
00044
00045 LocalEdge::LocalEdge(const Dims& inp_dims, const float& stdc, const float& smult, const float& ori, const uint& length, const uint density) : onReg(), offReg()
00046 {
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057 const float inter = (density == 1) ? 1.0F : (float)(length-1) / float(density-1);
00058 float dist = -1.0F * ((float)length - 1.0F) / 2.0F;
00059
00060 float offset;
00061 if (smult < 1.0)
00062 offset = 3.4110F * stdc;
00063 else
00064 {
00065 const float x1(-5.8399), x2(-3.1659), x3(-1.5079), x4(-0.7451), x5(3.4038);
00066 offset = x1 * exp(smult * x2) + x3 * exp(smult * x4) + x5 * stdc;
00067 }
00068
00069 const float offset2 = offset/2.0F;
00070
00071 for (uint ii = 0; ii < density; ++ii)
00072 {
00073
00074 const float x1 = dist; const float y1 = 0.0F;
00075 float xon = x1; float yon = y1 - offset2;
00076 float xoff = x1; float yoff = y1 + offset2;
00077
00078 const float xonr = xon * cos(ori) - yon * sin(ori);
00079 const float yonr = xon * sin(ori) + yon * cos(ori);
00080 const float xoffr = xoff * cos(ori) - yoff * sin(ori);
00081 const float yoffr = xoff * sin(ori) + yoff * cos(ori);
00082
00083 if ( (xonr >= 0) && (xonr < inp_dims.w()) && (yonr >= 0) && (yonr < inp_dims.h())
00084 && (xoffr >= 0) && (xoffr < inp_dims.w()) && (yoffr >= 0) && (yoffr < inp_dims.h()))
00085 {
00086 onReg.push_back(std::pair<float, float>(xonr, yonr));
00087 offReg.push_back(std::pair<float, float>(xoffr, yoffr));
00088 }
00089
00090 dist += inter;
00091 }
00092 }
00093
00094
00095 LocalEdge::LocalEdge() : onReg(), offReg()
00096 { }
00097
00098
00099 LocalEdge::~LocalEdge()
00100 { }
00101
00102
00103
00104
00105 template <class T_or_RGB>
00106 ImageSet<typename promote_trait<T_or_RGB, float>::TP>
00107 getScaleSpace(const Image<T_or_RGB>& input, const float& max_std)
00108 {
00109
00110
00111
00112 const float max_variance = max_std*max_std;
00113 const uint l = (max_variance > 4.0) ? log2(max_variance)+1 : 3;
00114
00115
00116 typedef typename promote_trait<T_or_RGB, float>::TP TP;
00117 Image<TP> inp = input;
00118 ImageSet<TP> pyr;
00119
00120
00121 pyr.push_back(inp);
00122 inp = lowPass5(inp);
00123 pyr.push_back(inp);
00124 inp = lowPass5(inp);
00125 pyr.push_back(inp);
00126 inp = lowPass5(lowPass5(inp));
00127 pyr.push_back(inp);
00128
00129 for (uint ii = 4; ii <= l; ii+=2)
00130 {
00131 inp = lowPass5yDecY(lowPass5xDecX(inp));
00132 pyr.push_back(inp);
00133 inp = lowPass5(lowPass5(inp));
00134 pyr.push_back(inp);
00135 }
00136 return pyr;
00137 }
00138
00139
00140 template <class T_or_RGB>
00141 void addScale(ImageSet<T_or_RGB>& pyr, const float& max_std)
00142 {
00143 ASSERT(pyr.size() >= 4);
00144
00145
00146
00147
00148 const float max_variance = max_std*max_std;
00149 const uint l = (max_variance > 4.0) ? log2(max_variance)+1 : 3;
00150 if (pyr.size() <= l)
00151 {
00152 Image<T_or_RGB> inp = pyr.back();
00153 for (uint ii = pyr.size()-1; ii <= l; ii+=2)
00154 {
00155 inp = lowPass5yDecY(lowPass5xDecX(inp));
00156 pyr.push_back(inp);
00157 inp = lowPass5(lowPass5(inp));
00158 pyr.push_back(inp);
00159 }
00160 }
00161 }
00162
00163
00164 template <class T_or_RGB>
00165 T_or_RGB getScaleSpacePixel(const ImageSet<T_or_RGB>& pyr, const float& x, const float& y, const float& std)
00166 {
00167 const int nlev = pyr.size();
00168 const float variance = std*std;
00169 const float lev = (variance >= 1.0F) ? log2(variance)+1 : variance;
00170 const int lev1 = int(floor(lev)); ASSERT(lev1 < nlev);
00171
00172
00173
00174
00175
00176 float facx = 1.0;
00177 float facy = 1.0;
00178 if (lev1 >= 4)
00179 {
00180 facx = pyr[0].getDims().w() / pyr[lev1].getDims().w();
00181 facy = pyr[0].getDims().h() / pyr[lev1].getDims().h();
00182 }
00183
00184 float ii1 = x / facx, jj1 = y / facy;
00185 const float ww1 = float(pyr[lev1].getWidth() - 1);
00186 const float hh1 = float(pyr[lev1].getHeight() - 1);
00187
00188 if (ii1 > ww1) ii1 = ww1;
00189 if (jj1 > hh1) jj1 = hh1;
00190
00191 const T_or_RGB val1 = pyr[lev1].getValInterp(ii1, jj1);
00192
00193
00194
00195 if (lev1 == nlev - 1) return val1;
00196
00197
00198 const uint lev2 = lev1 + 1;
00199 facx = 1.0;
00200 facy = 1.0;
00201 if (lev2 >= 4)
00202 {
00203 facx = pyr[0].getDims().w() / pyr[lev2].getDims().w();
00204 facy = pyr[0].getDims().h() / pyr[lev2].getDims().h();
00205 }
00206
00207 float ii2 = x / facx, jj2 = y / facy;
00208 const float ww2 = float(pyr[lev2].getWidth() - 1);
00209 const float hh2 = float(pyr[lev2].getHeight() - 1);
00210
00211 if (ii2 > ww2) ii2 = ww2;
00212 if (jj2 > hh2) jj2 = hh2;
00213
00214 const T_or_RGB val2 = pyr[lev2].getValInterp(ii2, jj2);
00215
00216
00217 const float fz = lev - float(lev1);
00218 return T_or_RGB(val1 + (val2 - val1) * fz);
00219 }
00220
00221
00222 template <class T_or_RGB>
00223 typename promote_trait<T_or_RGB, float>::TP
00224 getDiffScaleSpacePixel(const ImageSet<T_or_RGB>& pyr, const float& x, const float& y,
00225 const float& std_center, const float& std_surround, const bool on_center)
00226 {
00227 typedef typename promote_trait<T_or_RGB, float>::TP TP;
00228 const TP c = (TP)getScaleSpacePixel(pyr, x, y, std_center);
00229 const TP s = (TP)getScaleSpacePixel(pyr, x, y, std_surround);
00230 return (on_center) ? (c - s) : (s - c);
00231 }
00232
00233
00234 template <class T_or_RGB>
00235 typename promote_trait<T_or_RGB, float>::TP
00236 getEdgeScaleSpacePixel(const ImageSet<T_or_RGB>& pyr, const float& x, const float& y, const float& std, const LocalEdge& edgemap)
00237 {
00238 typedef typename promote_trait<T_or_RGB, float>::TP TP;
00239 TP sum = TP();
00240 for (uint ii = 0; ii < edgemap.onReg.size(); ++ii)
00241 {
00242 const float xon = edgemap.onReg[ii].first + x;
00243 const float yon = edgemap.onReg[ii].second + y;
00244 const float xoff = edgemap.offReg[ii].first + x;
00245 const float yoff = edgemap.offReg[ii].second + y;
00246
00247 const TP on = (TP)getScaleSpacePixel(pyr, xon, yon, std);
00248 const TP off = (TP)getScaleSpacePixel(pyr, xoff, yoff, std);
00249 sum += on - off;
00250 }
00251 sum /= (TP)edgemap.onReg.size();
00252 return sum;
00253 }
00254
00255
00256 template <class T_or_RGB>
00257 typename promote_trait<T_or_RGB, float>::TP
00258 getEdgeScaleSpacePixel(const ImageSet<T_or_RGB>& pyr, const float& x, const float& y, const float& stdc, const float& stds, const LocalEdge& edgemap)
00259 {
00260 typedef typename promote_trait<T_or_RGB, float>::TP TP;
00261 TP sum = TP();
00262 for (uint ii = 0; ii < edgemap.onReg.size(); ++ii)
00263 {
00264 const float xon = edgemap.onReg[ii].first + x;
00265 const float yon = edgemap.onReg[ii].second + y;
00266 const float xoff = edgemap.offReg[ii].first + x;
00267 const float yoff = edgemap.offReg[ii].second + y;
00268
00269 const TP on = getDiffScaleSpacePixel(pyr, xon, yon, stdc, stds, true);
00270 const TP off = getDiffScaleSpacePixel(pyr, xoff, yoff, stdc, stds, false);
00271 sum = on + off;
00272 }
00273 sum /= (TP)edgemap.onReg.size();
00274 return sum;
00275 }
00276
00277 #include "inst/SpaceVariant/ScaleSpaceOps.I"
00278
00279
00280
00281
00282
00283