📄 cannyedge.c
字号:
if((-deltaX[t] + deltaY[t]) >= 0){ // direction 5 (NWW) alpha = (float)deltaY[t] / deltaX[t]; mag1 = (1-alpha)*mag[t-1] + alpha*mag[t-x-1]; mag2 = (1-alpha)*mag[t+1] + alpha*mag[t+x+1]; }else{ // direction 6 (NNW) alpha = (float)deltaX[t] / deltaY[t]; mag1 = (1-alpha)*mag[t-x] + alpha*mag[t-x-1]; mag2 = (1-alpha)*mag[t+x] + alpha*mag[t+x+1]; } } } // non-maximal suppression // compare mag1, mag2 and mag[t] // if mag[t] is smaller than one of the neighbours then suppress it if((mag[t] < mag1) || (mag[t] < mag2)) nms[t] = SUPPRESSED; else{ if(mag[t] > 255) nms[t] = 255; else nms[t] = (unsigned char)mag[t]; } } // END OF ELSE (mag != 0) } // END OF FOR(j) } // END OF FOR(i)}///////////////////////////////////////////////////////////////////////////////// hysteresis thresholding// Remove weak edges and connect splitted edges// To connect edges, starting at a pixel which is greater than tHigh and search// all 8 neighbours. If the neighbour is greater than tLow, then it will also// become a edge.// The range of threshold is 0 < tLow < tHigh < 1.///////////////////////////////////////////////////////////////////////////////void hysteresis(unsigned char *nms, int x, int y, float tLow, float tHigh, unsigned char *out){ int i, j, t; unsigned short histo[256] = {0}; int sum, highCount; int lowTrigger, highTrigger; const unsigned char EDGE = 255; // clear out buffer(set all to 0) for(i = t = 0; i < y; i++) for(j = 0; j < x; j++, t++) out[t] = 0; // compute histogram to get high & low level trigger histogram(nms, x, y, histo, NULL, NULL); // find pixel count where tHigh(percentage) of pixels highCount = (x*y) * tHigh + 0.5; // compute low & high level trigger(threshold) i = 255; // max value in unsigned char sum = x * y; // total sum of histogram array while(sum > highCount){ sum -= histo[i]; i--; } highTrigger = ++i; lowTrigger = highTrigger * tLow + 0.5;#if 1 printf("HighTreshold: %4.2f, LowTreshold: %4.2f\n", tHigh, tLow); printf("HighTrigger: %d, LowTrigger: %d\n", highTrigger, lowTrigger);#endif // search a pixel which is greater than high level trigger // then mark it as an edge and start to trace edges using low trigger // If the neighbors are greater than low trigger, they become edges // NOTE: Use general thresholding method for faster computation, but // hysteresis thresholding can eliminates noise pixels. t = x + 1; // skip boundaries for(i = 1; i < y-1; i++, t+=2) for(j = 1; j < x-1; j++, t++) { if(nms[t] >= highTrigger){ out[t] = EDGE; traceEdge(nms, t, x, lowTrigger, out); } }}///////////////////////////////////////////////////////////////////////////////// search 8 neighbour pixels and trace edge if they are greater than threshold// This is recursive routine.///////////////////////////////////////////////////////////////////////////////void traceEdge(unsigned char *nms, int t, int numCols, int threshold, unsigned char *out){ int i, j, ptr; const unsigned char EDGE = 255; const unsigned char NOEDGE = 0; // check 8-connectivity of buf[t] for(i = -1; i <= 1; i++) for(j = -1; j <= 1; j++) { ptr = t + (i*numCols) + j; // get neighbour's pointer //printf("ptr: %d, nms[ptr]: %d\n", ptr, nms[t]); if(ptr == t) continue; // skip itself if(out[ptr] == EDGE) continue; if(nms[ptr] >= threshold){ out[ptr] = EDGE; // found edge // re-trace edges from at current point traceEdge(nms, ptr, numCols, threshold, out); }else out[ptr] = NOEDGE; }}///////////////////////////////////////////////////////////////////////////////// generate histogram of the image (input buffer is unsigned char, 1-Byte long)///////////////////////////////////////////////////////////////////////////////void histogram(unsigned char *buf, int x, int y, unsigned short *histo, int *min, int *max){ int bufLength = x * y; *min = *max = buf[0]; for(int i = 0; i < bufLength; i++) { histo[buf[i]]++; if(buf[i] < *min) *min = buf[i]; if(buf[i] > *max) *max = buf[i]; }}///////////////////////////////////////////////////////////////////////////////// generate histogram of the image (input buffer is short, 2-byte long)///////////////////////////////////////////////////////////////////////////////void histogram(unsigned short *buf, int x, int y, unsigned int *histo, int *min, int *max){ unsigned int i; unsigned int bufLength = x * y; *min = *max = buf[0]; for(i = 0; i < bufLength; i++) { histo[buf[i]]++; if(buf[i] < *min) *min = buf[i]; if(buf[i] > *max) *max = buf[i]; }}///////////////////////////////////////////////////////////////////////////////// Linear Interpolation of two points P1 & P2 where weight t// the range of weight(t) is 0 < t < 1.// Ohter than this range will be extrapolation.///////////////////////////////////////////////////////////////////////////////float linearInterp(float p1, float p2, float t){ float result; if(t <= 0) result = p1; else if(t > 0 && t < 1) result = (1 - t) * p1 + (t * p2); else if(t >= 1) result = p2; return result;}///////////////////////////////////////////////////////////////////////////////// Bi-Linear interpolation (2D)// interpolation on 2-D plane with 4 points// the range of weight(tx, ty) is 0 < tx(ty) < 1///////////////////////////////////////////////////////////////////////////////float bilinearInterp(float p1, float p2, float p3, float p4, float tx, float ty){ float x1, x2; // result of x(herizontal) drection float result; // interpolate X(horizontal) direction first if(tx <= 0){ x1 = p1; x2 = p3; } else if(tx > 0 && tx < 1){ x1 = (1 - tx) * p1 + (tx * p2); // point 1 & 2 x2 = (1 - tx) * p3 + (tx * p4); // point 3 & 4 } else if(ty >= 1){ x1 = p2; x2 = p4; } // interploate x1 & x2 in Y(vertical) direction if(ty <= 0) result = x1; else if(ty > 0 && ty < 1) result = (1 - ty) * x1 + (ty * x2); // point x1 & x2 else if(ty >= 1) result = x2; return result;}///////////////////////////////////////////////////////////////////////////////// thresholding using percent threshold parameter(0 ~ 1)// If pixel is under threshold(percent), set to zero.///////////////////////////////////////////////////////////////////////////////void threshold(unsigned char *buf, int x, int y, float p){ int i, j, t; int min, max; float level; // compute max and min value of image t = 0; min = max = buf[t]; for(i = 0; i < y; i++){ for(j = 0; j < x; j++, t++) { if(buf[t] < min) min = buf[t]; if(buf[t] > max) max = buf[t]; } } // compute threshold level level = p*(max-min)+ min; // thresholding t = 0; for(i = 0; i < y; i++){ for(j = 0; j < x; j++, t++) { if(buf[t] < level) buf[t] = 0; else buf[t] = 255; } } }//=============================================================================// CALLBACKS//=============================================================================void displayCB(void){ glutSetWindow(mainWin); glClear(GL_COLOR_BUFFER_BIT); // clear canvas //glutSwapBuffers(); // specify current paster position(coordinate) glRasterPos2i(0, SIZE_Y); // upper-left corner in openGL coordinates glPixelZoom(1.0, -1.0); // draw source image glDrawPixels(imgData->x, imgData->y, imgData->format, imgData->type, inBuf); //glColor3f(0,0,1); //drawString("Original Image", fontWidth, SIZE_Y-fontHeight, (void*)font); //glFlush(); glutSwapBuffers();}void displaySubWin1CB(void){ glutSetWindow(subWin1); glClear(GL_COLOR_BUFFER_BIT); // clear canvas // specify current paster position(coordinate) glRasterPos2i(0, SIZE_Y); // upper-left corner in openGL coordinates glPixelZoom(1.0, -1.0); // draw the processed image pixels glDrawPixels(imgData->x, imgData->y, imgData->format, imgData->type, outBuf); //glColor3f(1,0,0); //drawString("Gaussian Smooth", fontWidth, SIZE_Y-fontHeight, (void*)font); glutSwapBuffers();}void reshapeCB(int w, int h){ glViewport(0, 0, (GLsizei)w, (GLsizei)h); // main-window glutSetWindow(mainWin); //glutPositionWindow(100,100); //glutReshapeWindow(2*SIZE_X, SIZE_Y); //glViewport(0, 0, SIZE_X, SIZE_Y); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(0, SIZE_X, 0, SIZE_Y); // right sub-window glutSetWindow(subWin1); glutPositionWindow(SIZE_X, 0); glutReshapeWindow(SIZE_X, SIZE_Y); glViewport(0, 0, SIZE_X, SIZE_Y); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(0, SIZE_X, 0, SIZE_Y); glMatrixMode(GL_MODELVIEW); glLoadIdentity();}void keyboardHandlerCB(unsigned char key, int x, int y){ switch(key) { case 27: // ESCAPE free(imgData); free(inBuf); free(outBuf); glutDestroyWindow(subWin1); glutDestroyWindow(mainWin); exit(0); break; case 'r': case 'R': imgData->buf = (GLvoid*)inBuf; break; } // because this keyboard handler is shared, // redraw all windows whenever keyevents received glutSetWindow(mainWin); glutPostRedisplay(); glutSetWindow(subWin1); glutPostRedisplay();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -