首页 > 代码库 > 【CCL】连通区域提取

【CCL】连通区域提取

根据朋友给的一份原理写的 感觉还挺清楚

#include "cv.h"#include "highgui.h"#include <stdio.h>using namespace cv;#define MAXWIDTH 352#define MAXHEIGHT 288typedef struct PTNode{     int data;    int parent;}PTNode;void GetCCL(Mat &imgsrc, Mat &imgdst){    PTNode nodes[MAXWIDTH * MAXHEIGHT]; //线性树 数据的位置 与 数据本身 相同 即 nodes[x].data = http://www.mamicode.com/x       memset(nodes, 0, MAXWIDTH * MAXHEIGHT * sizeof(PTNode));    int nodenum = 0;    int row, col;    nodes[0].data = http://www.mamicode.com/0;    nodes[0].parent = -1;    for(row = 0; row < imgsrc.rows; row++)    {        for(col = 0; col < imgsrc.cols; col++)        {            if(imgsrc.at<uchar>(row, col) == 0) //像素为0的认为是背景 全黑色            {                imgdst.at<uchar>(row, col) = 0;            }            else //前景            {                if(row != 0 && col != 0) //不是边界                {                    if(imgsrc.at<uchar>(row, col) == imgsrc.at<uchar>(row, col - 1)) // 判断 先左 后上                     {                        imgdst.at<uchar>(row, col) = imgdst.at<uchar>(row, col - 1);  //如果和左边相同 标号和左边相同                        if(imgsrc.at<uchar>(row, col) == imgsrc.at<uchar>(row - 1, col) && imgdst.at<uchar>(row, col) != imgdst.at<uchar>(row - 1, col)) //同时与左边 上边相连  且两个序号不同                        {                            imgdst.at<uchar>(row, col) = (imgdst.at<uchar>(row, col) > imgdst.at<uchar>(row - 1, col)) ? imgdst.at<uchar>(row - 1, col) : imgdst.at<uchar>(row, col);  //取小的编号                            PTNode nodetmp1, nodetmp2;                            nodetmp1 = nodes[imgdst.at<uchar>(row, col - 1)];                            nodetmp2 = nodes[imgdst.at<uchar>(row - 1, col)];                            while(nodetmp1.parent != -1)                            {                                nodetmp1 = nodes[nodetmp1.parent];                            }                            while(nodetmp2.parent != -1)                            {                                nodetmp2 = nodes[nodetmp2.parent];                            }                            if(nodetmp2.data > nodetmp1.data)  //小的序号做parent 大序号做child                            {                                nodes[nodetmp2.data].parent = nodetmp1.data;  //这里一定要对nodes中的值修改, 直接写nodetmp2.parent = nodetmp1.data 是不行的因为nodetmp2只是一个局部变量 nodes[]里的值根本没有修改                            }                            else if(nodetmp2.data < nodetmp1.data)                            {                                nodes[nodetmp1.data].parent = nodetmp2.data;                            }                                                    }                    }                    else if(imgsrc.at<uchar>(row, col) == imgsrc.at<uchar>(row - 1, col)) //仅与上面相同 序号等于上面                    {                        imgdst.at<uchar>(row, col) = imgdst.at<uchar>(row - 1, col);                        }                    else //与两个方向的序号都不同 新建一个序号 序号与位置相同                    {                        nodenum++;                          imgdst.at<uchar>(row, col) = nodenum;                        nodes[imgdst.at<uchar>(row, col)].parent = -1;                        nodes[imgdst.at<uchar>(row, col)].data = http://www.mamicode.com/imgdst.at(row, col);                    }                }                else if(row == 0 && col != 0) //横向边界                {                    if(imgsrc.at<uchar>(row, col) == imgsrc.at<uchar>(row, col - 1))                    {                        imgdst.at<uchar>(row, col) = imgdst.at<uchar>(row, col - 1);                    }                    else                    {                        nodenum++;                        imgdst.at<uchar>(row, col) = nodenum;                        nodes[imgdst.at<uchar>(row, col)].parent = -1;                        nodes[imgdst.at<uchar>(row, col)].data = http://www.mamicode.com/imgdst.at(row, col);                    }                }                else if(col == 0 && row != 0) //竖向边界                {                    if(imgsrc.at<uchar>(row, col) == imgsrc.at<uchar>(row - 1, col))                    {                        imgdst.at<uchar>(row, col) = imgdst.at<uchar>(row - 1, col);                    }                    else                    {                        nodenum++;                        imgdst.at<uchar>(row, col) = nodenum;                        nodes[imgdst.at<uchar>(row, col)].parent = -1;                        nodes[imgdst.at<uchar>(row, col)].data = http://www.mamicode.com/imgdst.at(row, col);                    }                }                else //开始的(0 ,0)点 直接新建                {                    nodenum++;                    imgdst.at<uchar>(row, col) = nodenum;                    nodes[imgdst.at<uchar>(row, col)].parent = -1;                    nodes[imgdst.at<uchar>(row, col)].data = http://www.mamicode.com/imgdst.at(row, col);                }            }        }    }    //FILE * out = fopen("D:\\dst.txt", "w");    //for(row = 0; row < imgsrc.rows; row++)    //{    //    for(col = 0; col < imgsrc.cols; col++)    //    {    //        fprintf(out, "%d ", imgdst.at<uchar>(row, col));    //    }    //    fprintf(out, "\n");    //}    //把森林中每一个颗树都标成统一的颜色    for(row = 0; row < imgsrc.rows; row++)    {        for(col = 0; col < imgsrc.cols; col++)        {            PTNode nodetmp = nodes[imgdst.at<uchar>(row, col)];              while(nodetmp.parent != -1)            {                nodetmp = nodes[nodetmp.parent];            }            imgdst.at<uchar>(row, col) = nodetmp.data * 52 % 255; //随意设个颜色显示        }    }}void main(){    IplImage* img = cvLoadImage("D:\\Users\\CCL\\1.jpg", 0);    IplImage* imgdst = cvCreateImage(cvGetSize(img), 8, 1);    cvThreshold(img,img,125,255,0);    cvShowImage("ori", img);    Mat src(img), dst(imgdst);    GetCCL(src, dst);    cvShowImage("ccl", imgdst);    cvWaitKey(0);}

效果:

 

但是下面的图片出了问题:

 字母检测的很凌乱 

 

但是单独把一个字母拿出来 放大再检测就ok