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 "GUI/XWindow.H"
00039
00040 #include "Image/Image.H"
00041 #include "Image/Pixels.H"
00042
00043 #include "Component/ModelManager.H"
00044 #include "Devices/FrameGrabberFactory.H"
00045 #include "Util/Timer.H"
00046 #include "Util/Types.H"
00047 #include "Util/log.H"
00048 #include "Image/ColorOps.H"
00049 #include "Image/Image.H"
00050 #include "Image/MathOps.H"
00051 #include "Image/DrawOps.H"
00052 #include "Image/FilterOps.H"
00053 #include "Image/Transforms.H"
00054 #include "Raster/Raster.H"
00055 #include "BeoSub/hysteresis.H"
00056 #include "VFAT/segmentImageTrackMC.H"
00057 #include "rutz/shared_ptr.h"
00058 #include <cstdio>
00059 #include <cstdlib>
00060 #include <cstring>
00061 #include <iostream>
00062 #include <math.h>
00063
00064 #include "Image/Convolver.H"
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074 #define PI 3.14159265
00075 #define TRACE_CONTOUR_DEPTH_LIMIT 3
00076
00077
00078
00079 bool traceContour(const Image<float> &magnitudeImage, const int x, const int y, const int loThresh, const int hiThresh, const int from, const int steps) {
00080 if(magnitudeImage.getVal(x,y) >= hiThresh)
00081 return true;
00082 if(magnitudeImage.getVal(x,y) < loThresh)
00083 return false;
00084 if(x == 0 || x >= magnitudeImage.getWidth() - 1 || y == 0 || y >= magnitudeImage.getHeight() - 1)
00085 return false;
00086
00087 if(steps >= TRACE_CONTOUR_DEPTH_LIMIT)
00088 return false;
00089
00090 if(magnitudeImage.getVal(x-1,y) > loThresh && from != 1)
00091 if(traceContour(magnitudeImage, x-1, y, loThresh, hiThresh, 5, steps+1))
00092 return true;
00093 if(magnitudeImage.getVal(x-1,y-1) > loThresh && from != 2)
00094 if(traceContour(magnitudeImage, x-1, y-1, loThresh, hiThresh, 6, steps+1))
00095 return true;
00096 if(magnitudeImage.getVal(x-1,y+1) > loThresh && from != 8)
00097 if(traceContour(magnitudeImage, x-1, y+1, loThresh, hiThresh, 4, steps+1))
00098 return true;
00099 if(magnitudeImage.getVal(x,y-1) > loThresh && from != 3)
00100 if(traceContour(magnitudeImage, x, y-1, loThresh, hiThresh, 7, steps+1))
00101 return true;
00102 if(magnitudeImage.getVal(x,y+1) > loThresh && from != 7)
00103 if(traceContour(magnitudeImage, x, y+1, loThresh, hiThresh, 3, steps+1))
00104 return true;
00105 if(magnitudeImage.getVal(x+1,y-1) > loThresh && from != 4)
00106 if(traceContour(magnitudeImage, x+1, y-1, loThresh, hiThresh, 8, steps+1))
00107 return true;
00108 if(magnitudeImage.getVal(x+1,y) > loThresh && from != 5)
00109 if(traceContour(magnitudeImage, x+1, y, loThresh, hiThresh, 1, steps+1))
00110 return true;
00111 if(magnitudeImage.getVal(x+1,y+1) > loThresh && from != 6)
00112 if(traceContour(magnitudeImage, x+1, y+1, loThresh, hiThresh, 2, steps+1))
00113 return true;
00114
00115 return false;
00116 }
00117
00118 void nonMaxSuppressAndContTrace(Image<byte> &edgeImage, const Image<float> magnitudeImage, const Image<float> orientationImage, const int loThresh, const int hiThresh) {
00119 float mag, pa=0, pb=0, orientDeg;
00120
00121 for(int x = 1; x < magnitudeImage.getWidth() - 1; x++)
00122 for(int y = 1; y < magnitudeImage.getHeight() - 1; y++) {
00123 mag = magnitudeImage.getVal(x,y);
00124 orientDeg = orientationImage.getVal(x,y)*(180/PI);
00125
00126 if((orientDeg >= 0 && orientDeg <= 45) || (orientDeg > -180 && orientDeg <= -135)) {
00127 pa = (magnitudeImage.getVal(x+1,y) + magnitudeImage.getVal(x+1,y-1))/2;
00128 pb = (magnitudeImage.getVal(x-1,y) + magnitudeImage.getVal(x-1,y+1))/2;
00129 }
00130 else if((orientDeg > 45 && orientDeg <= 90) || (orientDeg > -135 && orientDeg <= -90)) {
00131 pa = (magnitudeImage.getVal(x+1,y-1) + magnitudeImage.getVal(x,y-1))/2;
00132 pb = (magnitudeImage.getVal(x-1,y+1) + magnitudeImage.getVal(x,y+1))/2;
00133 }
00134 else if((orientDeg > 90 && orientDeg <= 135) || (orientDeg > -90 && orientDeg <= -45)) {
00135 pa = (magnitudeImage.getVal(x,y-1) + magnitudeImage.getVal(x-1,y-1))/2;
00136 pb = (magnitudeImage.getVal(x,y+1) + magnitudeImage.getVal(x+1,y+1))/2;
00137 }
00138 else if((orientDeg > 135 && orientDeg <= 180) || (orientDeg > -45 && orientDeg < 0)) {
00139 pa = (magnitudeImage.getVal(x-1,y-1) + magnitudeImage.getVal(x-1,y))/2;
00140 pb = (magnitudeImage.getVal(x+1,y+1) + magnitudeImage.getVal(x+1,y))/2;
00141 }
00142
00143 if(mag > pa && mag > pb) {
00144 if(mag < loThresh)
00145 continue;
00146 else if(mag > hiThresh)
00147 edgeImage.setVal(x,y,255);
00148 else if(traceContour(magnitudeImage,x,y,loThresh,hiThresh, -1, 0)) {
00149 edgeImage.setVal(x,y,255);
00150 }
00151 }
00152 }
00153 }
00154
00155
00156 template <class T_or_RGB>
00157 Image<byte> cannyEdgeDetect(const Image<T_or_RGB> source, const float sigma, const int loThresh, const int hiThresh) {
00158
00159 Image<byte> edgeImage(source.getDims(), ZEROS);
00160 Image<float> magnitudeImage(source.getDims(), ZEROS);
00161 Image<float> orientationImage(source.getDims(), ZEROS);
00162
00163
00164 Image<float> fblurImage = luminance(convGauss(source, sigma, sigma,10));
00165
00166
00167 gradient(fblurImage, magnitudeImage, orientationImage);
00168
00169
00170 nonMaxSuppressAndContTrace(edgeImage, magnitudeImage, orientationImage, loThresh, hiThresh);
00171
00172 return edgeImage;
00173 }
00174
00175
00176
00177
00178 int main(int argc, char* argv[]) {
00179
00180 int loThresh, hiThresh;
00181 float sigma;
00182 Image< PixRGB<byte> > cameraImage;
00183 Image<float> floatImage;
00184
00185 if(argc != 4) {
00186 std::cout << "USAGE: bin/EdgeDetect sigma Tlow Thigh " << std::endl;
00187 std::cout << " *Thigh and Tlow are thresholds for the canny algorithm" << std::endl;
00188 std::cout << " *sigma is used in gaussian mask" << std::endl;
00189 exit(0);
00190 }
00191
00192 sigma = (float)atoi(argv[1]);
00193 loThresh = atoi(argv[2]);
00194 hiThresh = atoi(argv[3]);
00195
00196 XWindow* xwin;
00197 XWindow* xwin2;
00198
00199 ModelManager camManager("ColorTracker Tester");
00200 nub::soft_ref<FrameIstream> gb(makeIEEE1394grabber(camManager, "colorcam", "cocam"));
00201 camManager.addSubComponent(gb);
00202
00203 gb->setModelParamVal("FrameGrabberSubChan", 0);
00204 camManager.start();
00205
00206 cameraImage = gb->readRGB();
00207
00208 xwin = new XWindow(cameraImage.getDims());
00209 xwin2 = new XWindow(cameraImage.getDims());
00210
00211 while(1) {
00212 cameraImage = gb->readRGB();
00213
00214 xwin->drawImage(cameraImage);
00215
00216 xwin2->drawImage(cannyEdgeDetect(cameraImage, sigma, loThresh, hiThresh));
00217 }
00218 return 0;
00219 }
00220
00221
00222
00223
00224
00225