00001 /* 00002 * V1.C 00003 * 00004 * 00005 * Created by Randolph Voorhies on 12/5/07. 00006 * Copyright 2007 __MyCompanyName__. All rights reserved. 00007 * 00008 */ 00009 00010 #ifndef V1_H 00011 #define V1_H 00012 00013 00014 #include "Util/Types.H" 00015 #include "Util/log.H" 00016 #include "Image/ColorOps.H" 00017 #include "Image/Image.H" 00018 #include "Image/MathOps.H" 00019 #include "Image/DrawOps.H" 00020 #include "Image/FilterOps.H" 00021 #include "Image/Transforms.H" 00022 #include "Raster/Raster.H" 00023 #include "rutz/shared_ptr.h" 00024 00025 #include <vector> 00026 00027 #define TRACE_CONTOUR_DEPTH_LIMIT 3 00028 #define loThresh 10 00029 #define hiThresh 16 00030 #define sigma 2 00031 00032 00033 00034 class V1 { 00035 public: 00036 V1(Dims d); 00037 void processInput(Image<byte> i); 00038 bool traceContour(const Image<float> &magnitudeImage, const int x, const int y, const int from, const int steps); 00039 void nonMaxSuppressAndContTrace(Image<byte> &edgeImage, const Image<float> magnitudeImage, const Image<float> orientationImage); 00040 void cannyEdgeDetect(const Image<byte> source, Image<byte> &edgeImage, Image<float> &orientationImage); 00041 private: 00042 vector< Image<float> > layers; 00043 Image<byte> edgeImage; 00044 Dims itsDims; 00045 00046 00047 00048 00049 }; 00050 00051 V1::V1(Dims d) { 00052 itsDims = d; 00053 00054 layers.resize(THETA_LEVELS, Image<float>(d, ZEROS)); 00055 } 00056 00057 void V1::processInput(Image<byte> i) { 00058 00059 } 00060 00061 00062 //Depth limited search to trace contours 00063 bool V1::traceContour(const Image<float> &magnitudeImage, const int x, const int y, const int from, const int steps) { 00064 if(magnitudeImage.getVal(x,y) >= hiThresh) 00065 return true; 00066 if(magnitudeImage.getVal(x,y) < loThresh) 00067 return false; 00068 if(x == 0 || x >= magnitudeImage.getWidth() - 1 || y == 0 || y >= magnitudeImage.getHeight() - 1) 00069 return false; 00070 00071 if(steps >= TRACE_CONTOUR_DEPTH_LIMIT) 00072 return false; 00073 00074 if(magnitudeImage.getVal(x-1,y) > loThresh && from != 1) 00075 if(traceContour(magnitudeImage, x-1, y, 5, steps+1)) 00076 return true; 00077 if(magnitudeImage.getVal(x-1,y-1) > loThresh && from != 2) 00078 if(traceContour(magnitudeImage, x-1, y-1, 6, steps+1)) 00079 return true; 00080 if(magnitudeImage.getVal(x-1,y+1) > loThresh && from != 8) 00081 if(traceContour(magnitudeImage, x-1, y+1, 4, steps+1)) 00082 return true; 00083 if(magnitudeImage.getVal(x,y-1) > loThresh && from != 3) 00084 if(traceContour(magnitudeImage, x, y-1, 7, steps+1)) 00085 return true; 00086 if(magnitudeImage.getVal(x,y+1) > loThresh && from != 7) 00087 if(traceContour(magnitudeImage, x, y+1, 3, steps+1)) 00088 return true; 00089 if(magnitudeImage.getVal(x+1,y-1) > loThresh && from != 4) 00090 if(traceContour(magnitudeImage, x+1, y-1, 8, steps+1)) 00091 return true; 00092 if(magnitudeImage.getVal(x+1,y) > loThresh && from != 5) 00093 if(traceContour(magnitudeImage, x+1, y, 1, steps+1)) 00094 return true; 00095 if(magnitudeImage.getVal(x+1,y+1) > loThresh && from != 6) 00096 if(traceContour(magnitudeImage, x+1, y+1, 2, steps+1)) 00097 return true; 00098 00099 return false; 00100 } 00101 00102 void V1::nonMaxSuppressAndContTrace(Image<byte> &edgeImage, const Image<float> magnitudeImage, const Image<float> orientationImage) { 00103 float mag, pa=0, pb=0, orientDeg; 00104 00105 for(int x = 1; x < magnitudeImage.getWidth() - 1; x++) 00106 for(int y = 1; y < magnitudeImage.getHeight() - 1; y++) { 00107 mag = magnitudeImage.getVal(x,y); 00108 orientDeg = orientationImage.getVal(x,y)*(180/PI); 00109 00110 if((orientDeg >= 0 && orientDeg <= 45) || (orientDeg > -180 && orientDeg <= -135)) { 00111 pa = (magnitudeImage.getVal(x+1,y) + magnitudeImage.getVal(x+1,y-1))/2; 00112 pb = (magnitudeImage.getVal(x-1,y) + magnitudeImage.getVal(x-1,y+1))/2; 00113 } 00114 else if((orientDeg > 45 && orientDeg <= 90) || (orientDeg > -135 && orientDeg <= -90)) { 00115 pa = (magnitudeImage.getVal(x+1,y-1) + magnitudeImage.getVal(x,y-1))/2; 00116 pb = (magnitudeImage.getVal(x-1,y+1) + magnitudeImage.getVal(x,y+1))/2; 00117 } 00118 else if((orientDeg > 90 && orientDeg <= 135) || (orientDeg > -90 && orientDeg <= -45)) { 00119 pa = (magnitudeImage.getVal(x,y-1) + magnitudeImage.getVal(x-1,y-1))/2; 00120 pb = (magnitudeImage.getVal(x,y+1) + magnitudeImage.getVal(x+1,y+1))/2; 00121 } 00122 else if((orientDeg > 135 && orientDeg <= 180) || (orientDeg > -45 && orientDeg < 0)) { 00123 pa = (magnitudeImage.getVal(x-1,y-1) + magnitudeImage.getVal(x-1,y))/2; 00124 pb = (magnitudeImage.getVal(x+1,y+1) + magnitudeImage.getVal(x+1,y))/2; 00125 } 00126 00127 if(mag > pa && mag > pb) { 00128 if(mag < loThresh) 00129 continue; 00130 else if(mag > hiThresh) 00131 edgeImage.setVal(x,y,255); 00132 else if(traceContour(magnitudeImage,x,y, -1, 0)) { 00133 edgeImage.setVal(x,y,255); 00134 } 00135 } 00136 } 00137 } 00138 00139 void V1::cannyEdgeDetect(const Image<byte> source, Image<byte> &edgeImage, Image<float> &orientationImage) { 00140 00141 //Image<byte> edgeImage(source.getDims(), ZEROS); //Image to return 00142 Image<float> magnitudeImage(source.getDims(), ZEROS); //First Derivative Magnitude Image 00143 //Image<float> orientationImage(source.getDims(), ZEROS); //First Derivative Orientation Image 00144 00145 //gaussian blurred image -- to reduce noise 00146 Image<float> fblurImage = luminance(convGauss(source, sigma, sigma,10)); 00147 00148 //Find the magnitude and orientation 00149 gradient(fblurImage, magnitudeImage, orientationImage); 00150 00151 //Perform non-maximul suppression and contour tracing to determine edges 00152 nonMaxSuppressAndContTrace(edgeImage, magnitudeImage, orientationImage); 00153 00154 } 00155 00156 00157 #endif