2019-09-04 21:38:30 lengo 阅读数 477
  • 图解Java数据结构和算法

    1.算法是程序的灵魂,优秀的程序在对海量数据处理时,依然保持高速计算,就需要高效的数据结构和算法支撑。2.网上数据结构和算法的课程不少,但存在两个问题: 1)授课方式单一,大多是照着代码念一遍,数据结构和算法本身就比较难理解,对基础好的学员来说,还好一点,对基础不好的学生来说,基本上就是听天书了 2)说是讲数据结构和算法,但大多是挂羊头卖狗肉,算法讲的很少。 本课程针对上述问题,有针对性的进行了升级  3)授课方式采用图解+算法游戏的方式,让课程生动有趣好理解 4)系统全面的讲解了数据结构和算法, 除常用数据结构和算法外,还包括程序员常用10大算法:二分查找算法(非递归)、分治算法、动态规划算法、KMP算法、贪心算法、普里姆算法、克鲁斯卡尔算法、迪杰斯特拉算法、弗洛伊德算法、马踏棋盘算法。可以解决面试遇到的最短路径、最小生成树、最小连通图、动态规划等问题及衍生出的面试题,让你秒杀其他面试小伙伴 3.如果你不想永远都是代码工人,就需要花时间来研究下数据结构和算法。教程内容: 本教程是使用Java来讲解数据结构和算法,考虑到数据结构和算法较难,授课采用图解加算法游戏的方式。内容包括: 稀疏数组、单向队列、环形队列、单向链表、双向链表、环形链表、约瑟夫问题、栈、前缀、中缀、后缀表达式、中缀表达式转换为后缀表达式、递归与回溯、迷宫问题、八皇后问题、算法的时间复杂度、冒泡排序、选择排序、插入排序、快速排序、归并排序、希尔排序、基数排序(桶排序)、堆排序、排序速度分析、二分查找、插值查找、斐波那契查找、散列、哈希表、二叉树、二叉树与数组转换、二叉排序树(BST)、AVL树、线索二叉树、赫夫曼树、赫夫曼编码、多路查找树(B树B+树和B*树)、图、图的DFS算法和BFS、程序员常用10大算法、二分查找算法(非递归)、分治算法、动态规划算法、KMP算法、贪心算法、普里姆算法、克鲁斯卡尔算法、迪杰斯特拉算法、弗洛伊德算法马踏棋盘算法。 学习目标:通过学习,学员能掌握主流数据结构和算法的实现机制,开阔编程思路,提高优化程序的能力。

    3981 人正在学习 去看看 佟刚
clc;
clear all;
close all;
%提取连通分量测试图像,用来检测食物中的外来物
I=im2double(imread('D:\Gray Files\9-18a.tif'));
%获得图像大小
[M,N]=size(I);
%存放腐蚀后的图像
%设定提取门限,根据经验设定
th=0.808;
%将原图像根据上述门限进行二值处理,大于等于门限为1,小于为0
ind=find(I>=th);
I(ind)=1;
ind=find(I<th);
I(ind)=0;
%获得值为1的x,y坐标
[rows,cols]=find(I==1);
%将x,y坐标点组合成下标矩阵
index=cat(2,rows,cols);
%5*5结构元素
n=5;
B=ones(n,n);
n_l=floor(n/2);
%对边界图进行扩充,四周各加2行、2列0(与结构元素的大小相对应),目的是为了处理边界点
I_pad=padarray(I,[n_l,n_l]);
%将下标矩阵加2
index=index+2;
%保存所有连通对象集
Objs={};
%设定递归上限
set(0,'RecursionLimit',10000);
%递归寻找连通对象
while 1
    %取出下标矩阵中的第一个值
    if isempty(index)
        break;
    end
    %取出下标矩阵中的第一个对象
    p=index(1,:);
    A=FindConnectedPoint(p,I_pad,index,n_l);  
    %将边界线对象保存至对象集
    Objs=cat(1,Objs,A{1,1}-n_l);
    index=A{1,2}; 
    I_pad=A{1,3};        
end
%显示连通对象
J=zeros(M,N);
if ~isempty(Objs)
    for i=1:size(Objs,1)
        Obj=Objs{i,1};
        for j=1:size(Obj,1)
            J(Obj(j,1),Obj(j,2))=1;
        end
    end
end
imshow(J)

FindConnectedPoint函数如下:

function R=FindConnectedPoint(p,Beta_pad,ind,n_l)
    %保存边界坐标对象
    Obj=[];
    %以p为中心点,从边界图中取出3*3大小的块区域
    Block=Beta_pad(p(1,1)-n_l:p(1,1)+n_l,p(1,2)-n_l:p(1,2)+n_l);
    Obj=p;
    %将图像中的p点置零
    Beta_pad(p(1,1),p(1,2))=0;
    %将块区域中的p点置零
    Block(n_l+1,n_l+1)=0;
    A=cell(1,3);
    %将p点从下标矩阵中删除
    for j=1:size(ind,1)
        if ind(j,:)==p
            ind(j,:)=[];
            break;
        end
    end
    %寻找块区域中为1的点的下标
    [rows,cols]=find(Block==1);
    ind_sub=cat(2,rows,cols);
    if ~isempty(ind_sub)
        %确定块中数值为1的点的坐标
        for i=1:size(ind_sub,1) 
            p_next=[];
            if ind_sub(i,1)<=n_l+1
                p_next(1,1)=p(1,1)-abs(n_l+1-ind_sub(i,1));
                if ind_sub(i,2)<=n_l+1                    
                    p_next(1,2)=p(1,2)-abs(n_l+1-ind_sub(i,2));
                else
                    p_next(1,2)=p(1,2)+abs(n_l+1-ind_sub(i,2));                    
                end
            else
                p_next(1,1)=p(1,1)+abs(n_l+1-ind_sub(i,1));
                if ind_sub(i,2)<=n_l+1                    
                    p_next(1,2)=p(1,2)-abs(n_l+1-ind_sub(i,2));
                else
                    p_next(1,2)=p(1,2)+abs(n_l+1-ind_sub(i,2));                    
                end                
            end
            if Beta_pad(p_next(1,1),p_next(1,2))~=0                        
                A=FindConnectedPoint(p_next,Beta_pad,ind,n_l);
                Obj=cat(1,A{1,1},Obj);   
            end                       
            %更新下标矩阵
            ind=A{1,2};
            Beta_pad=A{1,3};
        end
    end
    %返回结果
    R={Obj,ind,Beta_pad};
end

 

2017-02-28 22:34:53 yi_tech_blog 阅读数 3604
  • 图解Java数据结构和算法

    1.算法是程序的灵魂,优秀的程序在对海量数据处理时,依然保持高速计算,就需要高效的数据结构和算法支撑。2.网上数据结构和算法的课程不少,但存在两个问题: 1)授课方式单一,大多是照着代码念一遍,数据结构和算法本身就比较难理解,对基础好的学员来说,还好一点,对基础不好的学生来说,基本上就是听天书了 2)说是讲数据结构和算法,但大多是挂羊头卖狗肉,算法讲的很少。 本课程针对上述问题,有针对性的进行了升级  3)授课方式采用图解+算法游戏的方式,让课程生动有趣好理解 4)系统全面的讲解了数据结构和算法, 除常用数据结构和算法外,还包括程序员常用10大算法:二分查找算法(非递归)、分治算法、动态规划算法、KMP算法、贪心算法、普里姆算法、克鲁斯卡尔算法、迪杰斯特拉算法、弗洛伊德算法、马踏棋盘算法。可以解决面试遇到的最短路径、最小生成树、最小连通图、动态规划等问题及衍生出的面试题,让你秒杀其他面试小伙伴 3.如果你不想永远都是代码工人,就需要花时间来研究下数据结构和算法。教程内容: 本教程是使用Java来讲解数据结构和算法,考虑到数据结构和算法较难,授课采用图解加算法游戏的方式。内容包括: 稀疏数组、单向队列、环形队列、单向链表、双向链表、环形链表、约瑟夫问题、栈、前缀、中缀、后缀表达式、中缀表达式转换为后缀表达式、递归与回溯、迷宫问题、八皇后问题、算法的时间复杂度、冒泡排序、选择排序、插入排序、快速排序、归并排序、希尔排序、基数排序(桶排序)、堆排序、排序速度分析、二分查找、插值查找、斐波那契查找、散列、哈希表、二叉树、二叉树与数组转换、二叉排序树(BST)、AVL树、线索二叉树、赫夫曼树、赫夫曼编码、多路查找树(B树B+树和B*树)、图、图的DFS算法和BFS、程序员常用10大算法、二分查找算法(非递归)、分治算法、动态规划算法、KMP算法、贪心算法、普里姆算法、克鲁斯卡尔算法、迪杰斯特拉算法、弗洛伊德算法马踏棋盘算法。 学习目标:通过学习,学员能掌握主流数据结构和算法的实现机制,开阔编程思路,提高优化程序的能力。

    3981 人正在学习 去看看 佟刚

应用背景:在许多自动图像分析应用中,如何识别出图像中的不同之处,往往是从其二值图像中提取连通分量。

连通分量的定义:令S是一个像素子集,如果S中的全部像素之间存在一个通路(m通路或8通路),则可以说两个像素p和q在S中是连通的。对于S中的任何像素p,S中连通到该像素的像素集称为S的连通分量。

2019-09-01 17:11:33 webzhuce 阅读数 535
  • 图解Java数据结构和算法

    1.算法是程序的灵魂,优秀的程序在对海量数据处理时,依然保持高速计算,就需要高效的数据结构和算法支撑。2.网上数据结构和算法的课程不少,但存在两个问题: 1)授课方式单一,大多是照着代码念一遍,数据结构和算法本身就比较难理解,对基础好的学员来说,还好一点,对基础不好的学生来说,基本上就是听天书了 2)说是讲数据结构和算法,但大多是挂羊头卖狗肉,算法讲的很少。 本课程针对上述问题,有针对性的进行了升级  3)授课方式采用图解+算法游戏的方式,让课程生动有趣好理解 4)系统全面的讲解了数据结构和算法, 除常用数据结构和算法外,还包括程序员常用10大算法:二分查找算法(非递归)、分治算法、动态规划算法、KMP算法、贪心算法、普里姆算法、克鲁斯卡尔算法、迪杰斯特拉算法、弗洛伊德算法、马踏棋盘算法。可以解决面试遇到的最短路径、最小生成树、最小连通图、动态规划等问题及衍生出的面试题,让你秒杀其他面试小伙伴 3.如果你不想永远都是代码工人,就需要花时间来研究下数据结构和算法。教程内容: 本教程是使用Java来讲解数据结构和算法,考虑到数据结构和算法较难,授课采用图解加算法游戏的方式。内容包括: 稀疏数组、单向队列、环形队列、单向链表、双向链表、环形链表、约瑟夫问题、栈、前缀、中缀、后缀表达式、中缀表达式转换为后缀表达式、递归与回溯、迷宫问题、八皇后问题、算法的时间复杂度、冒泡排序、选择排序、插入排序、快速排序、归并排序、希尔排序、基数排序(桶排序)、堆排序、排序速度分析、二分查找、插值查找、斐波那契查找、散列、哈希表、二叉树、二叉树与数组转换、二叉排序树(BST)、AVL树、线索二叉树、赫夫曼树、赫夫曼编码、多路查找树(B树B+树和B*树)、图、图的DFS算法和BFS、程序员常用10大算法、二分查找算法(非递归)、分治算法、动态规划算法、KMP算法、贪心算法、普里姆算法、克鲁斯卡尔算法、迪杰斯特拉算法、弗洛伊德算法马踏棋盘算法。 学习目标:通过学习,学员能掌握主流数据结构和算法的实现机制,开阔编程思路,提高优化程序的能力。

    3981 人正在学习 去看看 佟刚

基本概念

        提取连通分量的过程实际上也是标注连通分量的过程,通常的做法是给原图像中的每个连通区分配一个唯一代表该区域的编号,在输出图像中该连通区内的所有的像素值就赋值为该区域的编号,我们将这样的输出图像称为标注图像。这里介绍一种基于形态学的膨胀操作的提取连通分量的方法。
在这里插入图片描述
        以8连通的情况为例,对于图(a)的内含多个连通分量的图像A,从仅为连通分量A1内部某个的图像B开始,不断采用如图©所示的结构S进行膨胀。由于其他连通分量与A1之间至少有一条一像素宽的空白缝隙(如图(a)中的虚线),3*3的结构元素保证了只要B在区域A1内部,则每次膨胀都不会产生位于图像A中其他连通区域之内的点,这样只需用每次膨胀后的结构图像和原始图像A相交,就能把膨胀限制在A1内部。随着对B的不断膨胀,B的区域不断生长,但每次膨胀后与图像A的相交又将B限制在连通分量A1地内部,直到最终B充满整个连通分量A1,对连通分量A1地提取完毕。
在这里插入图片描述

示例演示

        我们用OpenCV实现连通分量提取函数,然后进行细菌计数。完整工程代码。

/*
 *only process binary image
 *iseight = true means eight connected, otherwise four connected
*/
int LabelConnectedComponent(const cv::Mat &src, cv::Mat &dst, bool iseight = true)
{
    Mat structelement;
    if(iseight)
        structelement = getStructuringElement(MORPH_RECT, Size(3, 3));
    else
         structelement = getStructuringElement(MORPH_CROSS, Size(3, 3));

    dst = Mat::ones(src.size(), src.type());
    Mat tmp = Mat::ones(src.size(), src.type()); // save last reuslt image
    Mat img = Mat::ones(src.size(), src.type()); //image B
    int labelnum = 0; //label of connected component

    Mat backupsrc;
    src.copyTo(backupsrc);
    for(int i = 0; i < backupsrc.rows; i++)
    {
        for(int j = 0; j < backupsrc.cols; j++)
        {
            if(backupsrc.at<uchar>(i, j) == 255)
            {
                Mat img = Mat::ones(src.size(), src.type());
                img.at<uchar>(i, j) = 255;
                img.copyTo(tmp);  //Temporary save
                labelnum++;

                while(true)  // until not change
                {
                    cv::dilate(img, img, structelement);
                    bitwise_and(img, src, img);
                    //if img do not change, this connected component is finished
                    if (cv::countNonZero(img - tmp) == 0)
                        break;
                    img.copyTo(tmp);
                }


                //label the connected component
                for(int r = 0; r < img.rows; r++)
                {
                    for(int c = 0; c < img.cols; c++)
                    {
                        if(img.at<uchar>(r, c) == 255)
                        {
                            backupsrc.at<uchar>(r, c) = 0;
                            dst.at<uchar>(r, c) = labelnum;
                        }
                    }
                }
            }
        }
    }
    return labelnum;
}

        先对原始图像进行膨胀
在这里插入图片描述
        然后进行细菌统计,实际的细菌个数为21。
在这里插入图片描述

2019-10-30 11:04:41 qq_37988883 阅读数 78
  • 图解Java数据结构和算法

    1.算法是程序的灵魂,优秀的程序在对海量数据处理时,依然保持高速计算,就需要高效的数据结构和算法支撑。2.网上数据结构和算法的课程不少,但存在两个问题: 1)授课方式单一,大多是照着代码念一遍,数据结构和算法本身就比较难理解,对基础好的学员来说,还好一点,对基础不好的学生来说,基本上就是听天书了 2)说是讲数据结构和算法,但大多是挂羊头卖狗肉,算法讲的很少。 本课程针对上述问题,有针对性的进行了升级  3)授课方式采用图解+算法游戏的方式,让课程生动有趣好理解 4)系统全面的讲解了数据结构和算法, 除常用数据结构和算法外,还包括程序员常用10大算法:二分查找算法(非递归)、分治算法、动态规划算法、KMP算法、贪心算法、普里姆算法、克鲁斯卡尔算法、迪杰斯特拉算法、弗洛伊德算法、马踏棋盘算法。可以解决面试遇到的最短路径、最小生成树、最小连通图、动态规划等问题及衍生出的面试题,让你秒杀其他面试小伙伴 3.如果你不想永远都是代码工人,就需要花时间来研究下数据结构和算法。教程内容: 本教程是使用Java来讲解数据结构和算法,考虑到数据结构和算法较难,授课采用图解加算法游戏的方式。内容包括: 稀疏数组、单向队列、环形队列、单向链表、双向链表、环形链表、约瑟夫问题、栈、前缀、中缀、后缀表达式、中缀表达式转换为后缀表达式、递归与回溯、迷宫问题、八皇后问题、算法的时间复杂度、冒泡排序、选择排序、插入排序、快速排序、归并排序、希尔排序、基数排序(桶排序)、堆排序、排序速度分析、二分查找、插值查找、斐波那契查找、散列、哈希表、二叉树、二叉树与数组转换、二叉排序树(BST)、AVL树、线索二叉树、赫夫曼树、赫夫曼编码、多路查找树(B树B+树和B*树)、图、图的DFS算法和BFS、程序员常用10大算法、二分查找算法(非递归)、分治算法、动态规划算法、KMP算法、贪心算法、普里姆算法、克鲁斯卡尔算法、迪杰斯特拉算法、弗洛伊德算法马踏棋盘算法。 学习目标:通过学习,学员能掌握主流数据结构和算法的实现机制,开阔编程思路,提高优化程序的能力。

    3981 人正在学习 去看看 佟刚

连通成分的标记原理

连通成分是给二值图像中的每个连通区域标上一个特定标号的算法,该算法可以用来对图像中的目标进行定位和计数。
邻域:
中间像素与他周围像素之间的位置关系决定了是几邻域连接,如下图表示了4邻域与8邻域
在这里插入图片描述在这里插入图片描述

算法思路

使用的数据结构为队列,用元组模仿队列,将像素的坐标值入队
1、从左到右,从上到下遍历每一个像素,判断该像素的像素值是否为1,并且判断它是否被标记过,如果没有被标记过并且像素值为1,则将该像素的位置入队。
2、查找该像素的8邻域内有没有像素值为1的并且没有被标记过的像素,有的话则给与它与该像素一样的标记,并且将该像素入队。
3、每次判断完一个像素的8邻域之后要记得将队列头加一。
4、队列为空之后即表示一个连通区域标记完成。则换一种标记,将队列置空,接着进行其他像素的判断。

Matlab代码

s=[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0;
   0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0;       %这个矩阵是维基百科中的矩阵
   0 1 1 1 1 1 1 1 1 0 0 1 1 1 1 0 0;
   0 0 0 1 1 1 1 0 0 0 1 1 1 1 0 0 0;
   0 0 1 1 1 1 0 0 0 1 1 1 0 0 1 1 0;
   0 1 1 1 0 0 0 0 0 0 0 1 1 1 0 0 0;
   0 0 1 1 0 0 0 0 0 1 0 0 0 0 0 1 0;
   0 0 0 0 0 0 1 1 1 1 0 0 1 1 1 1 0;
   0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0];

imshow(mat2gray(s));
[m n]=size(s);
tmp=zeros(m,n);     %标记图像
label=1;
queue_head=1;       %队列头
queue_tail=1;       %队列尾
neighbour=[-1 -1;-1 0;-1 1;0 -1;0 1;1 -1;1 0;1 1];  %和当前像素坐标相加得到八个邻域坐标

for i=2:m-1
    for j=2:n-1
        
        if s(i,j)==1 && tmp(i,j) ==0           
            tmp(i,j)=label;
            q{queue_tail}=[i j];        %用元组模拟队列,当前坐标入列
            queue_tail=queue_tail+1;
            
            while queue_head~=queue_tail
                pix=q{queue_head};                
                for k=1:8               %8邻域搜索
                    pix1=pix+neighbour(k,:);
                    if pix1(1)>=2 && pix1(1)<=m-1 && pix1(2) >=2 &&pix1(2)<=n-1  %边界条件的限定
                        if s(pix1(1),pix1(2)) == 1 && tmp(pix1(1),pix1(2)) ==0  %如果当前像素邻域像素为1并且标记图像的这个邻域像素没有被标记,那么标记
                          tmp(pix1(1),pix1(2))=label;
                          q{queue_tail}=[pix1(1) pix1(2)];
                          queue_tail=queue_tail+1;
                        end
                    end
                end
                queue_head=queue_head+1;
            end
            
            clear q;                %清空队列,为新的标记做准备
            label=label+1;
            queue_head=1;
            queue_tail=1;            
        end
    
    end
end
figure,imshow(mat2gray(tmp))

实验结果比较

在这里插入图片描述在这里插入图片描述

2014-06-15 08:42:45 pc1377318286 阅读数 2911
  • 图解Java数据结构和算法

    1.算法是程序的灵魂,优秀的程序在对海量数据处理时,依然保持高速计算,就需要高效的数据结构和算法支撑。2.网上数据结构和算法的课程不少,但存在两个问题: 1)授课方式单一,大多是照着代码念一遍,数据结构和算法本身就比较难理解,对基础好的学员来说,还好一点,对基础不好的学生来说,基本上就是听天书了 2)说是讲数据结构和算法,但大多是挂羊头卖狗肉,算法讲的很少。 本课程针对上述问题,有针对性的进行了升级  3)授课方式采用图解+算法游戏的方式,让课程生动有趣好理解 4)系统全面的讲解了数据结构和算法, 除常用数据结构和算法外,还包括程序员常用10大算法:二分查找算法(非递归)、分治算法、动态规划算法、KMP算法、贪心算法、普里姆算法、克鲁斯卡尔算法、迪杰斯特拉算法、弗洛伊德算法、马踏棋盘算法。可以解决面试遇到的最短路径、最小生成树、最小连通图、动态规划等问题及衍生出的面试题,让你秒杀其他面试小伙伴 3.如果你不想永远都是代码工人,就需要花时间来研究下数据结构和算法。教程内容: 本教程是使用Java来讲解数据结构和算法,考虑到数据结构和算法较难,授课采用图解加算法游戏的方式。内容包括: 稀疏数组、单向队列、环形队列、单向链表、双向链表、环形链表、约瑟夫问题、栈、前缀、中缀、后缀表达式、中缀表达式转换为后缀表达式、递归与回溯、迷宫问题、八皇后问题、算法的时间复杂度、冒泡排序、选择排序、插入排序、快速排序、归并排序、希尔排序、基数排序(桶排序)、堆排序、排序速度分析、二分查找、插值查找、斐波那契查找、散列、哈希表、二叉树、二叉树与数组转换、二叉排序树(BST)、AVL树、线索二叉树、赫夫曼树、赫夫曼编码、多路查找树(B树B+树和B*树)、图、图的DFS算法和BFS、程序员常用10大算法、二分查找算法(非递归)、分治算法、动态规划算法、KMP算法、贪心算法、普里姆算法、克鲁斯卡尔算法、迪杰斯特拉算法、弗洛伊德算法马踏棋盘算法。 学习目标:通过学习,学员能掌握主流数据结构和算法的实现机制,开阔编程思路,提高优化程序的能力。

    3981 人正在学习 去看看 佟刚


博客已转移至个人网站(http://www.p-chao.com)


C语言实现的二次遍历法提取连通分量


http://blog.csdn.net/pc1377318286/article/details/41414381            tip:这是这个算法的OpenCV接口版本链接地址



图像的最外框必须为黑色,添加黑色外框的部分代码我没有植入,使用时要特别注意

第一遍扫描检测联通状态,将其记录如静态线性链表中

第二遍扫描根据指针数组和静态线性链表恢复出图像

如果联通分量溢出,直接修改 int label[4096]={0};int labelcnt[4096]={0};int lcnt[4096]={0};

这三个数组的大小,关于图像数组的建立,请参见我的其它博客


如果提示堆栈溢出,在属性中修改堆栈大小即可,根据处理图像大小选择堆栈保留大小,建议在16M以上


输入图像:


提取结果:



操作源码:


void twopass(unsigned char image[Y_SIZE][X_SIZE],unsigned char imageget[Y_SIZE][X_SIZE])
{
	int i,j,cnt=0;
	int max=0,sec=0;
	int lmax;
	int lsec;
	int label[4096]={0};
	int labelcnt[4096]={0};
	int lcnt[4096]={0};
	int *plabel= label;
	int num,numt;
	int l=0;
	int *pimage[Y_SIZE][X_SIZE];
	int imageout[Y_SIZE][X_SIZE];
	unsigned char a,b,c,d;
	for(i=1;i<Y_SIZE;i++)
		for(j=1;j<X_SIZE-1;j++)
		{
			
			if( (i==1) && (j==1) )
			{	
				pimage[i-1][j-1]=NULL;
				pimage[i-1][j]=NULL;
				pimage[i-1][j+1]=NULL;
				pimage[i][j-1]=NULL;
			}
			else if( (i==1) && (j!=1) && (j!=X_SIZE-2) )
			{
				pimage[i-1][j+1]=NULL;
			}
			else if( (i==1) && (j==X_SIZE-2) )
			{
				pimage[i-1][j+1]=NULL;
				pimage[i][j+1]=NULL;
			}
			else if( (i!=1) && (j==1))
			{
				pimage[i][j-1]=NULL;
			}
			else if( (i!=1) && (j==X_SIZE-2) )
			{
				pimage[i][j+1]=NULL;
			}

 			if(image[i][j]==BLACK) pimage[i][j]=NULL;
			else
			{
				a=image[i-1][j-1];
				b=image[i-1][j];
				c=image[i-1][j+1];
				d=image[i][j-1];

				if( (a==0) && (b==0) && (c==0) && (d==0) )
				{
					plabel++;cnt++;
					pimage[i][j]=plabel;
				}//0
				else if( (a!=0) && (b==0) && (c==0) && (d==0) )
				{
					pimage[i][j]=pimage[i-1][j-1];
				}//1
				else if( (a==0) && (b!=0) && (c==0) && (d==0) )
				{
					pimage[i][j]=pimage[i-1][j];
				}//2
				else if( (a==0) && (b==0) && (c!=0) && (d==0) )
				{
					pimage[i][j]=pimage[i-1][j+1];
				}//3
				else if( (a==0) && (b==0) && (c==0) && (d!=0) )
				{
					pimage[i][j]=pimage[i][j-1];
				}//4
				else if( (a!=0) && (b!=0) && (c==0) && (d==0) )
				{
					pimage[i][j]=pimage[i-1][j-1];
				}//5
				else if( (a!=0) && (b==0) && (c!=0) && (d==0) )
				{
					pimage[i][j]=pimage[i-1][j-1];

					numt=*(pimage[i-1][j-1]);
					if(numt==0)
					{
						numt=(((int)pimage[i-1][j-1]-(int)label)/sizeof(int));
					}
					else
					{
						while(1)
						{
							if(label[numt]==0) break;
							else numt=label[numt];
						}
					}

					num=*(pimage[i-1][j+1]);
					if(num==0)
					{
						num=(((int)pimage[i-1][j+1]-(int)label)/sizeof(int));
					}
					else
					{
						while(1)
						{
							if(label[num]==0) break;
							else num=label[num];
						}
					}

					if(numt!=num) label[num]=numt;
				}//6
				else if( (a!=0) && (b==0) && (c==0) && (d!=0) )
				{
					pimage[i][j]=pimage[i-1][j-1];
				}//7
				else if( (a==0) && (b!=0) && (c!=0) && (d==0) )
				{
					pimage[i][j]=pimage[i-1][j];
				}//8
				else if( (a==0) && (b!=0) && (c==0) && (d!=0) )
				{
					pimage[i][j]=pimage[i-1][j];
				}//9
				else if( (a==0) && (b==0) && (c!=0) && (d!=0) )
				{
					pimage[i][j]=pimage[i-1][j+1];

					numt=*(pimage[i][j-1]);
					if(numt==0)
					{
						numt=(((int)pimage[i][j-1]-(int)label)/sizeof(int));
					}
					else
					{
						while(1)
						{
							if(label[numt]==0) break;
							else numt=label[numt];
						}
					}

					num=*(pimage[i-1][j+1]);
					if(num==0)
					{
						num=(((int)pimage[i-1][j+1]-(int)label)/sizeof(int));
					}
					else
					{
						while(1)
						{
							if(label[num]==0) break;
							else num=label[num];
						}
					}

					if(numt!=num) label[num]=numt;
				}//10
				else if( (a==0) && (b!=0) && (c!=0) && (d!=0) )
				{
					pimage[i][j]=pimage[i-1][j];
				}//11
				else if( (a!=0) && (b==0) && (c!=0) && (d!=0) )
				{
					pimage[i][j]=pimage[i-1][j-1];

					numt=*(pimage[i-1][j-1]);
					if(numt==0)
					{
						numt=(((int)pimage[i-1][j-1]-(int)label)/sizeof(int));
					}
					else
					{
						while(1)
						{
							if(label[numt]==0) break;
							else numt=label[numt];
						}
					}

					num=*(pimage[i-1][j+1]);
					if(num==0)
					{
						num=(((int)pimage[i-1][j+1]-(int)label)/sizeof(int));
					}
					else
					{
						while(1)
						{
							if(label[num]==0) break;
							else num=label[num];
						}
					}

					if(numt!=num) label[num]=numt;
				}//12
				else if( (a!=0) && (b!=0) && (c==0) && (d!=0) )
				{
					pimage[i][j]=pimage[i-1][j-1];
				}//13
				else if( (a!=0) && (b!=0) && (c!=0) && (d==0) )
				{
					pimage[i][j]=pimage[i-1][j-1];
				}//14
				else if( (a!=0) && (b!=0) && (c!=0) && (d!=0) )
				{
					pimage[i][j]=pimage[i-1][j-1];
				}//15

			}
		}

	for(i=0;i<Y_SIZE;i++)
	{
		for(j=0;j<X_SIZE;j++)
		{
			if(pimage[i][j]!=NULL)
			{
				num=*(pimage[i][j]);
				if(num==0)
				{
					num=(((int)pimage[i][j]-(int)label)/sizeof(int));
				}
				else
				{
					while(1)
					{
						if(label[num]==0) break;
						else num=label[num];
					}
				}
				if(labelcnt[num]==0)
				{
					l++;
					labelcnt[num]=l;
				}
				imageout[i][j]=labelcnt[num];
				lcnt[labelcnt[num]]++;
			}
			else imageout[i][j]=0;
		}
	}

	for(i=0;i<l+1;i++)
	{
		if(lcnt[i]>max)
		{
			max=lcnt[i];
			lmax=i;
		}
	}

	for(i=0;i<l;i++)
		if( (lcnt[i]>sec) && (lcnt[i]<max) )
		{
			sec=lcnt[i];
			lsec=i;
		}


	for(i=0;i<Y_SIZE;i++)
		for(j=0;j<X_SIZE;j++)
		{
			if(imageout[i][j]==lmax) imageget[i][j]=WHITE;
			else imageget[i][j]=BLACK;
		}
}


期中的逻辑还可以再优化,为便于分析,列出了15条,事实上可以简化为6条


if( (a==0) && (b==0) && (c==0) && (d==0) )
				{
					plabel++;cnt++;
					pimage[i][j]=plabel;
				}//0
				else if( (a==0) && (b==0) && (c!=0) && (d==0) )
				{
					pimage[i][j]=pimage[i-1][j+1];
				}//3
				else if( (a==0) && (b==0) && (c==0) && (d!=0) )
				{
					pimage[i][j]=pimage[i][j-1];
				}//4
				else if( (a!=0) && (b==0) && (c!=0)  )
				{
					pimage[i][j]=pimage[i-1][j-1];

					numt=*(pimage[i-1][j-1]);
					if(numt==0)
					{
						numt=(((int)pimage[i-1][j-1]-(int)label)/sizeof(int));
					}
					else
					{
						while(1)
						{
							if(label[numt]==0) break;
							else numt=label[numt];
						}
					}

					num=*(pimage[i-1][j+1]);
					if(num==0)
					{
						num=(((int)pimage[i-1][j+1]-(int)label)/sizeof(int));
					}
					else
					{
						while(1)
						{
							if(label[num]==0) break;
							else num=label[num];
						}
					}

					if(numt!=num) label[num]=numt;
				}//6
				else if( (a==0) && (b!=0) )
				{
					pimage[i][j]=pimage[i-1][j];
				}//8
				else if( (a==0) && (b==0) && (c!=0) && (d!=0) )
				{
					pimage[i][j]=pimage[i-1][j+1];

					numt=*(pimage[i][j-1]);
					if(numt==0)
					{
						numt=(((int)pimage[i][j-1]-(int)label)/sizeof(int));
					}
					else
					{
						while(1)
						{
							if(label[numt]==0) break;
							else numt=label[numt];
						}
					}

					num=*(pimage[i-1][j+1]);
					if(num==0)
					{
						num=(((int)pimage[i-1][j+1]-(int)label)/sizeof(int));
					}
					else
					{
						while(1)
						{
							if(label[num]==0) break;
							else num=label[num];
						}
					}

					if(numt!=num) label[num]=numt;
				}//10
				else
				{
					pimage[i][j]=pimage[i-1][j-1];
				}//15



没有更多推荐了,返回首页