00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <cmath>
00024 #include <queue>
00025
00026
00027
00028 #include "Canny.hpp"
00029
00030
00031
00032
00033
00034 namespace kn{
00035
00036
00037 void canny(kn::ImageGS8u &inputImage, kn::ImageGS8u &outputImage, unsigned int lowerThres, unsigned int upperThres){
00038
00039 char kx[9] = {1,0,-1,2,0,-2,1,0,-1};
00040 char ky[9] = {1,2,1,0,0,0,-1,-2,-1};
00041 ImageGSf direction(inputImage.width(),inputImage.height());
00042 ImageGS8u norme(inputImage.width(),inputImage.height());
00043
00044 for(unsigned int j = 1; j < inputImage.height()-1; j++){
00045 for(unsigned int i = 1; i < inputImage.width()-1; i++){
00046 int gx = 0;
00047 int gy = 0;
00048 for(int dy = -1; dy < 2; dy++){
00049 for(int dx = -1; dx < 2; dx++){
00050 gx+=inputImage(i+dx, j+dy)*kx[(1+dx)+(1+dy)*3];
00051 gy+=inputImage(i+dx, j+dy)*ky[(1+dx)+(1+dy)*3];
00052 }
00053 }
00054 norme(i,j) = std::sqrt(gx*gx+gy*gy);
00055 direction(i,j) = std::atan2(gy,gx);
00056 if(direction(i,j) < 0)direction(i,j)+=M_PI;
00057 }
00058 }
00059
00060 double part0 = M_PI/8;
00061 double part1 = 3*M_PI/8;
00062 double part2 = 5*M_PI/8;
00063 double part3 = 7*M_PI/8;
00064
00065
00066 for(unsigned int j = 0; j < inputImage.height(); j++){
00067 for(unsigned int i = 0; i < inputImage.width(); i++){
00068 if(j == 0 || i == 0 || j == inputImage.height()-1 || i == inputImage.width()-1 || norme(i,j)<=lowerThres){
00069 outputImage(i,j) = 0;
00070 continue;
00071 }
00072 if(direction(i,j) > part3 || direction(i,j) < part0){
00073 if(norme(i,j)>norme(i-1,j) && norme(i,j)>norme(i+1,j))
00074 outputImage(i,j) = norme(i,j);
00075 else
00076 outputImage(i,j) = 0;
00077 }else if(direction(i,j) > part2){
00078 if(norme(i,j)>norme(i-1,j+1) && norme(i,j)>norme(i+1,j-1))
00079 outputImage(i,j) = norme(i,j);
00080 else
00081 outputImage(i,j) = 0;
00082 }else if(direction(i,j) > part1){
00083 if(norme(i,j)>norme(i,j+1) && norme(i,j)>norme(i,j-1))
00084 outputImage(i,j) = norme(i,j);
00085 else
00086 outputImage(i,j) = 0;
00087 } else{
00088 if(norme(i,j)>norme(i+1,j+1) && norme(i,j)>norme(i-1,j-1))
00089 outputImage(i,j) = norme(i,j);
00090 else
00091 outputImage(i,j) = 0;
00092 }
00093 }
00094 }
00095
00096
00097
00098 for(unsigned int j = 1; j < inputImage.height()-1; j++){
00099 for(unsigned int i = 1; i < inputImage.width()-1; i++){
00100 if(outputImage(i,j) >= upperThres){
00101 std::queue<unsigned int> fifo;
00102 fifo.push(i+j*inputImage.width());
00103 while(!fifo.empty()){
00104 unsigned int ind = fifo.front();
00105 fifo.pop();
00106 unsigned int x = ind%inputImage.width();
00107 unsigned int y = ind/inputImage.width();
00108 for(int dy = -1; dy < 2; dy++){
00109 for(int dx = -1; dx < 2; dx++){
00110 if(outputImage(x+dx,y+dy) > lowerThres && outputImage(x+dx,y+dy) < upperThres){
00111 outputImage(x+dx,y+dy) = upperThres;
00112 fifo.push(x+dx+(y+dy)*inputImage.width());
00113 }
00114 }
00115 }
00116 }
00117 }
00118 }
00119 }
00120 for(unsigned int j = 1; j < inputImage.height()-1; j++){
00121 for(unsigned int i = 1; i < inputImage.width()-1; i++){
00122 if(outputImage(i,j) >= upperThres)
00123 outputImage(i,j) = 255;
00124 else
00125 outputImage(i,j) = 0;
00126 }
00127 }
00128 }
00129
00130
00131
00132
00133 }
00134
00135