Opencv——基于索引表的图像细化
圖像細化針對的是二值圖像? 或者用閥值處理的二值圖像。基于索引表的細化算法大致是遍歷被二值化圖像的邊緣,根據邊緣點的八連通域情況查找索引表以確定該邊緣點是否能夠被刪除。根據一些細化規則我們可以建立索引表,因此我們的主要工作就是不斷地遍歷邊緣進行是否刪除判斷,直至邊緣的每一個點都不能再被細化(刪除)。
(1):例子 左邊為輸入圖像 右邊為細化的效果圖
(2)思想:
公式: y = p0*2^0 + p1*2^1+ p2*2^2 + p3*2^3 + p4*2^4 + p5*2^5 + p6*2^6 +p7*2^7
這八個點的取值范圍為{0,1}?? (1表示255)
對于這八個點的不同取值情況,按如下順序表示的二進制的值也將有不同的取值
| ?P7? | ?P6? | ?P5? | ?P4? | ?P3? | ?P2? | ?P1? | ?P0? | ?Sum? | ?Delete Enable? |
| ? | ? | ? | ? | ? | ? | ? | ? | ? | ? |
其中Sum的取值從0~255,Delete Enable為1表示可以刪除,為0表示不能刪除,這樣我們就建立了一個索引表deletemark[256]
???????? 前輩們對此作出了總結,得出每個點周圍8領域的256種情況,放在一個char data[256]的數組中,不可以刪除用0來表示,能被刪除的用1來表示。然后對圖像進行處理得到二值圖像<0和1>,掃描圖像,根據公式得出y,依次用data[y]判斷該點是否可以被刪除,直到所有的點都不可以被刪除為止。
(3)算法步驟:
(4)代碼:
#include <stdlib.h> #include <string.h>#include "cv.h" #include "highgui.h" #include "cxcore.h"//基于索引表的細化細化算法 //功能:對圖象進行細化 //參數:lpDIBBits:代表圖象的一維數組 // lWidth:圖象高度 // lHeight:圖象寬度 // 無返回值 bool ThiningDIBSkeleton (unsigned char* lpDIBBits, int lWidth, int lHeight) { //循環變量long i;long j;long lLength;unsigned char deletemark[256] = { // 這個即為前人據8領域總結的是否可以被刪除的256種情況0,0,0,0,0,0,0,1, 0,0,1,1,0,0,1,1,0,0,0,0,0,0,0,0, 0,0,1,1,1,0,1,1,0,0,0,0,0,0,0,0, 1,0,0,0,1,0,1,1,0,0,0,0,0,0,0,0, 1,0,1,1,1,0,1,1,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 1,0,0,0,1,0,1,1,1,0,0,0,0,0,0,0, 1,0,1,1,1,0,1,1,0,0,1,1,0,0,1,1, 0,0,0,1,0,0,1,1,0,0,0,0,0,0,0,0, 0,0,0,1,0,0,1,1,1,1,0,1,0,0,0,1, 0,0,0,0,0,0,0,0,1,1,0,1,0,0,0,1, 1,1,0,0,1,0,0,0,0,1,1,1,0,0,1,1, 0,0,0,1,0,0,1,1,0,0,0,0,0,0,0,0, 0,0,0,0,0,1,1,1,1,1,1,1,0,0,1,1, 1,1,0,0,1,1,0,0,1,1,1,1,0,0,1,1, 1,1,0,0,1,1,0,0};//索引表unsigned char p0, p1, p2, p3, p4, p5, p6, p7;unsigned char *pmid, *pmidtemp; // pmid 用來指向二值圖像 pmidtemp用來指向存放是否為邊緣unsigned char sum;bool bStart = true;lLength = lWidth * lHeight;unsigned char *pTemp = new uchar[sizeof(unsigned char) * lWidth * lHeight](); //動態創建數組 并且初始化// P0 P1 P2// P7 P3// P6 P5 P4while(bStart){bStart = false;//首先求邊緣點pmid = (unsigned char *)lpDIBBits + lWidth + 1;memset(pTemp, 0, lLength);pmidtemp = (unsigned char *)pTemp + lWidth + 1; // 如果是邊緣點 則將其設為1for(i = 1; i < lHeight -1; i++) {for(j = 1; j < lWidth - 1; j++){if( *pmid == 0) //是0 不是我們需要考慮的點{pmid++;pmidtemp++;continue;}p3 = *(pmid + 1);p2 = *(pmid + 1 - lWidth);p1 = *(pmid - lWidth);p0 = *(pmid - lWidth -1);p7 = *(pmid - 1);p6 = *(pmid + lWidth - 1);p5 = *(pmid + lWidth);p4 = *(pmid + lWidth + 1); sum = p0 & p1 & p2 & p3 & p4 & p5 & p6 & p7;if(sum == 0){*pmidtemp = 1; // 這樣周圍8個都是1的時候 pmidtemp==1 表明是邊緣 }pmid++;pmidtemp++;}pmid++;pmid++;pmidtemp++;pmidtemp++;}//現在開始刪除pmid = (unsigned char *)lpDIBBits + lWidth + 1;pmidtemp = (unsigned char *)pTemp + lWidth + 1;for(i = 1; i < lHeight -1; i++) // 不考慮圖像第一行 第一列 最后一行 最后一列{for(j = 1; j < lWidth - 1; j++){if( *pmidtemp == 0) //1表明是邊緣 0--周圍8個都是1 即為中間點暫不予考慮{pmid++;pmidtemp++;continue;}p3 = *(pmid + 1);p2 = *(pmid + 1 - lWidth);p1 = *(pmid - lWidth);p0 = *(pmid - lWidth -1);p7 = *(pmid - 1);p6 = *(pmid + lWidth - 1);p5 = *(pmid + lWidth);p4 = *(pmid + lWidth + 1);p1 *= 2;p2 *= 4;p3 *= 8;p4 *= 16;p5 *= 32;p6 *= 64;p7 *= 128;sum = p0 | p1 | p2 | p3 | p4 | p5 | p6 | p7;// sum = p0 + p1 + p2 + p3 + p4 + p5 + p6 + p7;if(deletemark[sum] == 1){*pmid = 0;bStart = true; // 表明本次掃描進行了細化}pmid++;pmidtemp++;}pmid++;pmid++;pmidtemp++;pmidtemp++;}}delete []pTemp;return true; }int main(int argc, char* argv[]) {IplImage* src = cvLoadImage("E:\\study_opencv_video\\testthin\\char2.png",0);cvThreshold(src,src,100,255,CV_THRESH_BINARY);unsigned char* imagedata ;cvNamedWindow("s",0);cvShowImage("s" , src);imagedata = new uchar[sizeof(char)*src->width*src->height]();int x , y;for(y=0;y<src->height;y++){unsigned char* ptr = (unsigned char*)(src->imageData + y*src->widthStep);for(x=0;x<src->width;x++){imagedata[y*src->width+x] = ptr[x] > 0 ? 1 : 0;}}ThiningDIBSkeleton(imagedata,src->width,src->height);for(y=0;y<src->height;y++){unsigned char* ptr = (unsigned char*)(src->imageData + y*src->widthStep);for(x=0;x<src->width;x++){ptr[x] = imagedata[y*src->width + x]>0? 255 : 0;}}cvNamedWindow("src",0);cvShowImage("src" , src);cvWaitKey(0);delete []imagedata;return 0; }//
?轉載:https://blog.csdn.net/lu597203933/article/details/14397605
總結
以上是生活随笔為你收集整理的Opencv——基于索引表的图像细化的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C++模板的一些基础知识
- 下一篇: MFC制作计算器