免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 4113 | 回复: 5
打印 上一主题 下一主题

发个求图像凸包并填充其内部的程序 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2007-04-10 14:11 |只看该作者 |倒序浏览
/*******************************************************************************************
* Filename     :  OverlapStampProcess.cpp                                                      
*Creat by elite for XXXXXXX Tech LTD.                                                               
********************************************************************************************/
#include <stdlib.h>
#include <stdio.h>
#include <string>

#include "OverlapStampProcess.h"


typedef struct point{
        int x;
        int y;
} point;

#define element point
#define IncLen 20//栈增长长度
/***************************************************************************/
/***用C语言实现栈类***用C语言实现栈类***用C语言实现栈类***用C语言实现栈类****************/
/***************************************************************************/


typedef struct StackClass{
        element *top;
        element *base;
        int EleNum;
        int StackLength;
        void (*push)(struct StackClass *,element);//插入元素
        bool (*pop)(struct StackClass *,element &;//删除元素
        //struct StackClass* this_p //this指针
}stack;
//***********************************************************//
//*函数功能:元素入栈                                                                                        //
//++++++++++++++++++++++++++++++++++++++++++++++++++++//
void f_push(stack *s,element e)
{
        element *temp;

        if((s->EleNum)+1<=s->StackLength)
        {
                s->top[0] = e;
                s->EleNum++;
                s->top++;
        }
        else
        {
                temp = new element[(s->StackLength)+IncLen];
                memcpy(temp,s->base,(s->StackLength)*sizeof(element));
                delete[] s->base;
                s->base = temp;
                s->top = temp + (s->EleNum);
                s->StackLength = s->StackLength + IncLen;

                s->top[0] = e;

                s->EleNum++;
                s->top++;
        }
}
//***********************************************************//
//*函数功能:元素出栈                                                                                       //
//++++++++++++++++++++++++++++++++++++++++++++++++++++//
bool f_pop(stack *s,element &e)
{
        element temp;
        if(s->EleNum>=1)
        {

                s->top--;
                temp = s->top[0];
                s->EleNum--;
                e = temp;

                return true;
        }
        else
        {
                printf("The stack is empty, No element to pop !";
                return false;
        }
}
//***********************************************************//
//*函数功能:栈的构造函数                                                                                 //
//++++++++++++++++++++++++++++++++++++++++++++++++++++//
stack *StackCreat(int Length)
{
        stack *temp = NULL;

        temp = new stack[1];
        temp->base = new element[Length];
        temp->top = temp->base;
        temp->StackLength = Length;
        temp->EleNum = 0;
        temp->push = f_push;
        temp->pop = f_pop;
        //temp->this_p = temp;  

        return temp;
}
//***********************************************************//
//*函数功能:栈的析构函数                                                                                 //
//++++++++++++++++++++++++++++++++++++++++++++++++++++//
void StackDestroy(stack *s)
{
        delete[] s->base;
        delete[] s;
        s = NULL;                                                                           
}                                                                                          
//****************************************************************************//
//***用C语言实现栈类***用C语言实现栈类***用C语言实现栈类***用C语言实现栈类*****************//
//***************************************************************************//

typedef struct s_figure{
        point* p;
        int PointNumber;
}figure;//保存图像轮廓的数据元素
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
//+函数功能:寻找轮廓(对图像最好先进行膨胀处理,填充断裂)                                           //
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
figure GetFigure(unsigned char* img, int SizeX, int SizeY)
{
        int i,j,k;
        bool sign = false;
        point tmp;
        figure rst;

        rst.p = new point[2*SizeX*SizeY];
        rst.PointNumber = 0;

        k = 0;
        //get the top-left points and insert it
        for(i = 0;i < SizeY;i++)
        {
                for(j = 0;j < SizeX;j++)
                {
                        if(img[i*SizeX + j] == 255)
                        {
                                rst.p[k].x = j;
                                rst.p[k].y = i;
                                tmp.x = j;
                                tmp.y = i;
                                k++;
                                sign = true;
                                break;
                        }
                }
                if(sign == true)
                        break;
        }
        //get the top-right points and insert it
        for(i = 0;i < SizeY;i++)
        {
                for(j = SizeX - 1;j > -1;j--)
                {
                        if(img[i*SizeX + j] == 255)
                        {
                                rst.p[k].x = j;
                                rst.p[k].y = i;
                                k++;
                                sign = true;
                                break;
                        }
                }
                if(sign == true)
                        break;
        }
        //judge if top-left == top-right ?
        if((rst.p[k].x == rst.p[k-1].x)&&(rst.p[k].y == rst.p[k-1].y))
        {
                k--;
        }
       
        //get the other points and insert it
        for(i = rst.p[k-1].y+1;i < SizeY;i++)
                for(j = SizeX-1;j > -1;j--)
                {
                        if(img[i*SizeX + j] == 255)
                        {
                                rst.p[k].x = j;
                                rst.p[k].y = i;
                                k++;
                                break;
                        }
                }
   
        //delete bottom-left point
    k--;
   
        //get the bottom-left point
        for(i = SizeY - 1;i > -1;i--)
        {
                for(j = 0;j < SizeX;j++)
                {
                        if(img[i*SizeX + j] == 255)
                        {
                                rst.p[k].x = j;
                                rst.p[k].y = i;
                                k++;
                                sign = true;
                                break;
                        }
                }
                if(sign == true)
                        break;
        }

        //judge if bottom-left == bottom-right ?
        if((rst.p[k].x == rst.p[k-1].x)&&(rst.p[k].y == rst.p[k-1].y))
        {
                k--;
        }

        //get the other points and insert it
        for(i = rst.p[k-1].y-1;i > tmp.y;i--)
                for(j = 0;j < SizeX;j++)
                {
                        if(img[i*SizeX + j] == 255)
                        {
                                rst.p[k].x = j;
                                rst.p[k].y = i;
                                k++;
                                break;
                        }
                }


        figure rst1;
        rst1.p = new point[k];
        rst1.PointNumber = k;

        memcpy(rst1.p,rst.p,k*sizeof(point));
        delete[] rst.p;

        return rst1;

}

//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
//+函数功能:对blob进行排序                                 //
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
void sort(point *ESrc,int NumSrc,point *&EDst)
{
        int i,/*Min,*/MinY;
        //int point;
        //int *EDst;

        EDst = new point[NumSrc];

        MinY = 0;
        for(i=1;i<NumSrc;i++)
        {
                if(ESrc.y < ESrc[MinY].y) MinY = i;
        }
        /*
        for(i=0;i<=MinY;i++)
        {
                if(ESrc.y == ESrc[MinY].y)
                {
                        Min = i;
                        break;
                }
        }
        */
        if(MinY == 0) memcpy(EDst,ESrc,NumSrc*sizeof(point));
        else
        {
                memcpy(EDst,ESrc+MinY,(NumSrc-MinY)*sizeof(point));

                memcpy(EDst+NumSrc-MinY,ESrc,MinY*sizeof(point));
        }
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
//+函数功能:对blob进行水平序排序                           //
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
void Qsort(point *ESrc,int NumSrc,point *&EDst)
{}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
//+函数功能:求线段拐向                                     //
//说明:如果回值大于0,说明NowPoint在线段next-top的右侧;如果  //
//等于0,在同一直线上;如果小于0,在线段左侧.                  //
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
int GetCross(point next,point top,point NowPoint)
{
        point d1,d2;
        int cross;

        d1.x = NowPoint.x - next.x;
        d1.y = NowPoint.y - next.y;

        d2.x = top.x - next.x;
        d2.y = top.y - next.y;

        cross = d1.x*d2.y - d1.y*d2.x;

        return cross;
}

//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
//+函数功能:求凸包边界                                      //
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
void Convex(point *EpSrc,int NumSrc,point *&EDst,int &NumDst)//考虑用队列传入参数
{

        point *ESort = NULL;//存储排序后的blob
        point *ESrc = NULL;
        int i,j;

        stack *s = NULL;
        element top,next;//存储栈中弹出进行比较的元素


        //对blob排序
        sort(EpSrc,NumSrc,ESort);//排序问题----have bug

        ESrc = new point[NumSrc+1];
        memcpy(ESrc,ESort,NumSrc*sizeof(point));//Add first point
        ESrc[NumSrc].y = ESort[0].y;
        ESrc[NumSrc].x = ESort[0].x;

        //求取凸包边点
        s = StackCreat(NumSrc*2);
        s->push(s,ESrc[0]);//入栈数据未变
        s->push(s,ESrc[1]);
        for(i=2;i<NumSrc+1;i++)//对所有点进行定顶点法则判定
        {
                int temp = s->EleNum;
                for(j=temp;j>1;j--)//回溯所有已经入栈的点
                {
                        s->pop(s,top);
                        s->pop(s,next);
                        if(GetCross(next,top,ESrc)<0)//如果cross大于零则当前点位于线段top-next右侧
                        {
                                //当前点也入栈,然后跳出循环
                                s->push(s,next);
                                s->push(s,top);
                                s->push(s,ESrc);

                                break;
                        }
                        //栈顶元素出栈,继续计算当前点是否边界点
                        else s->push(s,next);
                }
                if(s->EleNum == 1) s->push(s,ESrc);//如果栈中只剩起始点,则将当前点压入栈顶
        }
        //丢弃栈顶元素,因为起点重复
        s->pop(s,top);

        //输出凸包边点
        NumDst = s->EleNum;
        EDst = new point[NumDst];
        point temp;
        for(i=0;i<NumDst;i++)
        {
                s->pop(s,temp);
                EDst[NumDst - 1 - i].x = temp.x;
                EDst[NumDst - 1 - i].y = temp.y;
        }

        //释放内存
        delete[] ESort;
        //销毁栈
        StackDestroy(s);

}



//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
//+函数功能:计算库章凸包                                   //
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
figure CptStampCvx(unsigned char* img, int SizeX, int SizeY)
{
        figure src,dst;
        src = GetFigure(img, SizeX, SizeY);
        Convex(src.p,src.PointNumber,dst.p,dst.PointNumber);

        delete src.p;
        return dst;

}

//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
//+函数功能:判断两点是否八邻域连接                         //
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
bool IsNear(point p1, point p2, int SizeX, int SizeY)
{
        int x1,x2,y1,y2;
        int length = SizeX - 1,high = SizeY - 1;

        x1 = p1.x - 1;
        x2 = p1.x + 1;
        y1 = p1.y - 1;
        y2 = p1.y + 1;

        if(x1 < 0)
                x1 = 0;
        if(x2 > length)
                x2 = length;
        if(y1 < 0)
                y1 = 0;
        if(y2 > high)
                y2 = high;

        if(p2.x < x2 && p2.x > x1 && p2.y < y2 && p2.y > y1)
        {
                return true;
        }
        else
        {
                return false;
        }
}


//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
//+函数功能:构造凸包连续边界                               //
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
void ConnectConvex(unsigned char* img, int SizeX, int SizeY,
                           point* PointList, int num)
{
        int i;
        bool sign = false;
        stack *s;//用队列或链表保存结果

        s = StackCreat(100*num);

        s->push(s,PointList[0]);
        printf("saved p 0 \n";
        for(i = 1;i < num;i++)//num
        {
                //store(PointList);
                //s->push(s,PointList);

                sign = IsNear(PointList[i-1], PointList, SizeX, SizeY);
                if(sign == false)
                {
                        int diffx,diffy;
                        diffx = PointList.x - PointList[i-1].x;
                        diffy = PointList.y - PointList[i-1].y;

                        if(diffx == 0)
                        {
                                int start,end;
                            if(PointList[i-1].y < PointList.y)
                                {
                                    start = PointList[i-1].y;
                                    end = PointList.y;
                                }
                            else
                                {
                                    end = PointList[i-1].y;
                                    start = PointList.y;
                                }

                            point NewPoint;
                                NewPoint.x = PointList[i-1].x;
                                for(NewPoint.y = start+1;NewPoint.y < end;(NewPoint.y)++)
                                {
                                    s->push(s,NewPoint);
                                }
                        }
                        else
                        {
                                if(diffy == 0)
                                {
                                        int start,end;
                                       if(PointList[i-1].x < PointList.x)
                                        {
                                      start = PointList[i-1].x;
                                            end = PointList.x;
                                        }
                                           else
                                        {
                                                end = PointList[i-1].x;
                                            start = PointList.x;
                                        }

                                    point NewPoint;
                                        NewPoint.y = PointList[i-1].y;
                                        for(NewPoint.x = start+1;NewPoint.x < end;(NewPoint.x)++)
                                        {
                                            s->push(s,NewPoint);
                                        }
                                }
                                else
                                {
                                        int a,b;
                                    a = 10000*diffy/diffx;
                                            b = 10000*PointList.y - a*PointList.x;
            
                                    int start,end;                           
                                    point NewPoint;
                                    if(abs(diffx) > abs(diffy))
                                        {
                                                if(PointList[i-1].x < PointList.x)
                                                {
                                                start = PointList[i-1].x;
                                                end = PointList.x;
                                                }
                                        else
                                                {
                                                end = PointList[i-1].x;
                                                start = PointList.x;
                                                }

                                                for(NewPoint.x = start+1;NewPoint.x < end;(NewPoint.x)++)
                                            {
                                                    NewPoint.y = a*(NewPoint.x)+b;
                                                    NewPoint.y = ((NewPoint.y)+5000)/10000;

                                            //store(NewPoint);
                                                    s->push(s,NewPoint);
                                            }
                                        }
                                        else
                                        {
                                                if(PointList[i-1].y < PointList.y)
                                                {
                                                start = PointList[i-1].y;
                                                end = PointList.y;
                                                }
                                        else
                                                {
                                                        end = PointList[i-1].y;
                                                start = PointList.y;
                                                }

                                                for(NewPoint.y = start+1;NewPoint.y < end;(NewPoint.y)++)
                                            {
                                                    NewPoint.x = (10000*NewPoint.y -b)/a;
                                                        NewPoint.x = ((NewPoint.x)*10 + 5)/10;

                                           //store(NewPoint);
                                                    s->push(s,NewPoint);
                                            }
                                        }
                                }

                        }
                }
                else
                {
                        s->push(s,PointList);
                        printf("saved p %d \n",i);
                }
                s->push(s,PointList);
        }
      
        memset(img, 0, 3*SizeX*SizeY);
        int size = SizeX*SizeY;
        point p;       
       
        do
        {
                s->pop(s,p);
                img[p.y*SizeX+p.x] = 128;
                //img[size+p.y*SizeX+p.x] = 250;
                //img[2*size+p.y*SizeX+p.x] = 250;
        } while(s->EleNum > 1);

        StackDestroy(s);
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
//+函数功能:填充凸包内部                               //
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
void FillImg(unsigned char* img, int SizeX, int SizeY)
{
        int i,j/*,StartX,StartY,EndX,EndY*/;

        for(i = 0;i < SizeY; i++)
                for(j = 0;j < SizeX;j++)
                {
                        int size = i*SizeX+j;
                        if(img[size] != 12
                        {
                                img[size] = 255;
                        }
                        else
                        {
                                break;
                        }
                }
        for(i = 0;i < SizeY; i++)
                for(j = SizeX-1;j > -1;j--)
                {
                        int size = i*SizeX+j;
                        if(img[size] != 12
                        {
                                img[size] = 255;
                        }
                        else
                        {
                                break;
                        }
                }
        for(i = 0;i < SizeY; i++)
                for(j = 0;j < SizeX;j++)
                {
                        int size = i*SizeX+j;
                        if(img[size] == 12
                        {
                                img[size] = 255;
                        }
                        else
                        {
                                img[size] = 255 - img[size];
                        }
                }

}

底下其他函数不贴了

[ 本帖最后由 zhichiamd 于 2007-4-19 12:37 编辑 ]

原始.JPG (8.83 KB, 下载次数: 47)

原始图像

原始图像

结果.JPG (3.03 KB, 下载次数: 50)

处理后图像

处理后图像

论坛徽章:
0
2 [报告]
发表于 2007-04-10 14:15 |只看该作者
unsigned char* img 为指向内存中指向存储图像数据的指针,长度为SizeX*SizeY;SizeX, SizeY为图像宽和高。
计算过程先计算出图像的边界轮廓点,然后从这些轮廓点中找出凸包点,连接凸包点,填充凸包内部。

写完没用上,发来大家看看吧。
经过调试没有bug了

论坛徽章:
0
3 [报告]
发表于 2007-04-10 18:09 |只看该作者
Graham Scaning 那段写得好长...
其他部分看不懂干嘛的...

论坛徽章:
0
4 [报告]
发表于 2007-04-19 12:39 |只看该作者
附上处理前后的图像,应该容易明白这个作什么的了:)
PS:CU的表情符号真讨厌

[ 本帖最后由 zhichiamd 于 2007-4-19 12:41 编辑 ]

论坛徽章:
0
5 [报告]
发表于 2016-01-05 18:59 |只看该作者
后面几个的表情在12后面的 实际是哪些内容

论坛徽章:
24
狮子座
日期:2013-12-31 10:48:0015-16赛季CBA联赛之吉林
日期:2016-04-18 14:43:1015-16赛季CBA联赛之北控
日期:2016-05-18 15:01:4415-16赛季CBA联赛之上海
日期:2016-06-22 18:00:1315-16赛季CBA联赛之八一
日期:2016-06-25 11:02:2215-16赛季CBA联赛之佛山
日期:2016-08-17 22:48:2615-16赛季CBA联赛之福建
日期:2016-12-27 22:39:272016科比退役纪念章
日期:2017-02-08 23:49:4315-16赛季CBA联赛之八一
日期:2017-02-16 01:05:3415-16赛季CBA联赛之山东
日期:2017-02-22 15:34:5615-16赛季CBA联赛之上海
日期:2017-11-25 16:17:5015-16赛季CBA联赛之四川
日期:2016-01-17 18:38:37
6 [报告]
发表于 2016-01-05 19:33 |只看该作者
zhichiamd 发表于 2007-04-19 12:39
附上处理前后的图像,应该容易明白这个作什么的了:)
PS:CU的表情符号真讨厌


      贴代码需要这样:
  1. #include <iostream>

  2. using namespace std;

  3. int main()
  4. {
  5.     cout << "Hello world!" << endl;
  6.     return 0;
  7. }
复制代码
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP