26 #include "CannyEdge.hh"
30 template<
class InputStorageType,
class OutputStorageType>
34 useAbsThresholds_ =
false;
53 template<
class InputStorageType,
class OutputStorageType>
57 template<
class InputStorageType,
class OutputStorageType>
78 magnitude.
Init(w_,h_,1);
83 SmoothImage_(src, smoothed);
85 CalculateGradients_(smoothed, gx, gy, magnitude, gdir, dst);
90 template<
class InputStorageType,
class OutputStorageType>
98 gauss_.SetSigma(gsigma_);
99 gauss_.Filter(tmp, smoothed);
103 template<
class InputStorageType,
class OutputStorageType>
106 int res = Filter(src,
110 intermediaries[3], dst);
114 template<
class InputStorageType,
class OutputStorageType>
121 tmpx.
Init(w_*2, h_*2, 1);
122 tmpy.
Init(w_*2, h_*2, 1);
123 ConvX_.Filter(src, tmpx);
124 ConvY_.Filter(src, tmpy);
135 for (
unsigned int y=0;y<h_*2;y+=2) {
136 for (
unsigned int x=0;x<w_*2;x+=2) {
137 idaY[y/2][x/2] = idaTY[y][x];
138 idaX[y/2][x/2] = idaTX[y][x];
142 for (
unsigned int y=0;y<h_;y++) {
143 for (
unsigned int x=0;x<w_;x++) {
144 idaM[y][x] = (OutputStorageType)(abs((
double)(idaY[y][x]))+abs((
double)(idaX[y][x])));
148 for (
unsigned int y=0;y<h_;y++) {
149 for (
unsigned int x=0;x<w_;x++) {
150 if (idaX[y][x] == 0) {
151 if (idaY[y][x] == 0) {
154 if (idaY[y][x] < 0) {
155 idaY[y][x] = -idaY[y][x];
159 }
else if(idaX[y][x]<0 && idaY[y][x]>0) {
160 idaD[y][x] = (OutputStorageType)(180 - ((atan((
double)(idaY[y][x])/(
double)( -idaX[y][x]))) * (180/M_PI)));
161 }
else if(idaX[y][x]>0 && idaY[y][x]<0) {
162 idaD[y][x] = (OutputStorageType)(180 - ((atan((
double)( -idaY[y][x])/(
double)(idaX[y][x]))) * (180/M_PI)));
164 idaD[y][x] = (OutputStorageType)((atan((
double)(idaY[y][x])/(
double)(idaX[y][x]))) * (180/M_PI));
166 if(idaD[y][x] < 22.5)
168 else if(idaD[y][x] < 67.5)
170 else if(idaD[y][x] < 112.5)
172 else if(idaD[y][x] < 157.5)
179 OutputStorageType highThreshold = thresHighAbs_;
180 OutputStorageType lowThreshold = thresLowAbs_;
181 if (!useAbsThresholds_) {
182 DetermineThresholds_(magnitude, lowThreshold, highThreshold);
183 BIASCDOUT(D_FILTERBASE_CALLSTACK,
"CannyEdge determined thresholds: " << lowThreshold <<
" " << highThreshold);
184 if (lowThreshold == highThreshold) {
187 BIASWARN(
"CannyEdge could not determine thresholds automatically, resetting to: " << lowThreshold <<
" " << highThreshold);
191 for (
unsigned int y=edgeWidth_;y<h_-edgeWidth_;y++) {
192 for (
unsigned int x=edgeWidth_;x<w_-edgeWidth_;x++) {
193 OutputStorageType leftNeighbor;
194 OutputStorageType rightNeighbor;
195 if(idaD[y][x] == 0) {
196 leftNeighbor = idaM[y][x-edgeWidth_];
197 rightNeighbor = idaM[y][x+edgeWidth_];
198 }
else if(idaD[y][x] == 45) {
199 leftNeighbor = idaM[y+edgeWidth_][x-edgeWidth_];
200 rightNeighbor = idaM[y-edgeWidth_][x+edgeWidth_];
201 }
else if(idaD[y][x] == 90) {
202 leftNeighbor = idaM[y-edgeWidth_][x];
203 rightNeighbor = idaM[y+edgeWidth_][x];
205 leftNeighbor = idaM[y-edgeWidth_][x-edgeWidth_];
206 rightNeighbor = idaM[y+edgeWidth_][x+edgeWidth_];
208 if (idaM[y][x] < leftNeighbor || idaM[y][x] < rightNeighbor) {
211 if(idaM[y][x] >= highThreshold) {
213 }
else if(idaM[y][x] < lowThreshold) {
217 for (
unsigned int yw=y-1;yw<=y+1;yw++) {
218 for (
unsigned int xw=x-1;xw<=x+1;xw++) {
219 if (idaR[yw][xw]>=highThreshold) {
233 template <
class InputStorageType,
class OutputStorageType>
235 BIASERR(
"no parameter support");
239 template<
class InputStorageType,
class OutputStorageType>
243 OutputStorageType min, max;
245 if (max==0 || max==min) {
246 BIASERR(
"can not determine thresholds");
249 unsigned int histo[256];
250 unsigned int idx = 0;
251 for (;idx<256;idx++) {
255 unsigned int upperPercent = allPixelCount * thresHigh_ / 100;
256 unsigned int lowerPercent = allPixelCount * thresLow_ / 100;
257 for (
unsigned int i=0;i<allPixelCount;i++) {
258 idx = (
unsigned int)((
float)(ida[i] - min) / (
float)(max-min) * 255.0f);
262 while (histo[idx] <= upperPercent) {
263 upperPercent -= histo[idx];
266 high = (OutputStorageType)((
float)idx / 255.0f * (max-min) + min);
268 while (histo[idx] <= lowerPercent) {
269 lowerPercent -= histo[idx];
272 low = (OutputStorageType)((
float)idx / 255.0f * (max-min) + min);
276 template<
class InputStorageType,
class OutputStorageType>
283 template<
class InputStorageType,
class OutputStorageType>
286 useAbsThresholds_ =
true;
287 thresLowAbs_ = lowAbs_;
288 thresHighAbs_ = highAbs_;
292 template<
class InputStorageType,
class OutputStorageType>
295 useAbsThresholds_ =
false;
301 template<
class InputStorageType,
class OutputStorageType>
304 edgeWidth_ = edgeWidth;
313 #define FILTER_INSTANTIATION_CLASS CannyEdge
314 #define FILTER_INSTANTIATION_NO_UNSIGNED_OUTPUT
317 #ifdef BUILD_IMAGE_CHAR
318 #define CANNYUNDEF_CHAR
319 #undef BUILD_IMAGE_CHAR
322 #ifdef BUILD_IMAGE_USHORT
323 #undef BUILD_IMAGE_USHORT
324 #define CANNYUNDEF_USHORT
327 #include "Filterinst.hh"
329 #ifdef CANNYUNDEF_CHAR
330 #define BUILD_IMAGE_CHAR
331 #undef CANNYUNDEF_CHAR
334 #ifdef CANNYUNDEF_USHORT
335 #define BUILD_IMAGE_USHORT
336 #undef CANNYUNDEF_USHORT
339 #undef FILTER_INSTANTIATION_NO_UNSIGNED_OUTPUT
340 #undef FILTER_INSTANTIATION_CLASS
void Release()
reimplemented from ImageBase
CannyEdge()
Constructor, setting default values.
int SmoothImage_(const Image< InputStorageType > &src, Image< OutputStorageType > &smoothed)
int DetermineThresholds_(const Image< OutputStorageType > &src, OutputStorageType &low, OutputStorageType &high)
bool IsEmpty() const
check if ImageData_ points to allocated image buffer or not
int CalculateGradients_(const Image< OutputStorageType > &src, Image< OutputStorageType > &gx, Image< OutputStorageType > &gy, Image< OutputStorageType > &magnitude, Image< OutputStorageType > &gdir, Image< OutputStorageType > &dst)
Down-, Upsampling routines and Resize.
void GetMinMaxPixelValue(StorageType &min, StorageType &max, unsigned short int channel=0, unsigned int *mincoo=NULL, unsigned int *maxcoo=NULL) const
returns the minimal and maximal pixel value in channel only Finds minimum and maximum pixel value in ...
unsigned int GetWidth() const
int SetThresholdsAbsolute(OutputStorageType lowAbs_, OutputStorageType highAbs_)
set absolute value of low and high thresholds for hysteresis in magnitude gradient image ...
unsigned int GetChannelCount() const
returns the number of Color channels, e.g.
virtual int Filter(const Image< InputStorageType > &src, Image< OutputStorageType > &dst)
scales the src to dst using the downsampling factor from SetFactor()
int SetThresholdsRelative(unsigned int low_, unsigned int high_)
set value of low and high thresholds for hysteresis in magnitude gradient image in terms of percent o...
unsigned int GetHeight() const
int SetGaussSigma(float sigma)
before edge detection, the input image is blurred with a gaussian. Set sigma here (defaults to 1...
void Init(unsigned int Width, unsigned int Height, unsigned int channels=1, enum EStorageType storageType=ST_unsignedchar, const bool interleaved=true)
calls Init from ImageBase storageType is ignored, just dummy argument
const StorageType * GetImageData() const
overloaded GetImageData() from ImageBase
virtual void GetBordersValid_(int &border_x, int &border_y) const
not implemented
int SetEdgeWidth(unsigned int edgeWidth)
set edge width for hysteresis.
unsigned long int GetPixelCount() const
returns number of pixels in image
A filter mask (or a kernel) used for convolution.
void SetFactor(double factor)
the downsampling factor
virtual int Filter(const Image< InputStorageType > &src, Image< OutputStorageType > &gx, Image< OutputStorageType > &gy, Image< OutputStorageType > &magnitude, Image< OutputStorageType > &gdir, Image< OutputStorageType > &dst)
call for getting all intermediary results
const StorageType ** GetImageDataArray() const
overloaded GetImageDataArray() from ImageBase