我想做图像的轮廓提取,针对256色的bmp图。
有什么固定的模式吗?有什么好的算法吗?

解决方案 »

  1.   

    刚在BCB版看到的,自己改成delphi的吧 
    ====================================================================
    下面是使用拉普拉斯算子对图像提取边缘的代码,运行后能够实现预想的效果,但是很费时!
    大家能否给出优化代码以提高处理速度的建议吗?
    void __fastcall TForm1::BitBtn1Click(TObject *Sender)
    {
        int oper[3][3] = {{0,1,0},{1,-4,1},{0,1,0}};//拉普拉斯模板
        H_Filtering(Image1->Picture->Bitmap,Image1->Picture->Bitmap,oper);
    }void H_Filtering(Graphics::TBitmap *srcBitmap,Graphics::TBitmap *dstBitmap,int oper[3][3])
    {
        int red,green,blue;
        int w = srcBitmap->Width,
    h = srcBitmap->Height;
        Graphics::TBitmap *bitmap= new Graphics::TBitmap();
        bitmap->Height = h;
        bitmap->Width = w;
        for(int i=1;i<w-1;i++){
    for(int j=1;j<h-1;j++){
    //分别对R、G、B分量进行计算
        red =0;
        green =0;
        blue =0;
        for(int u=-1;u<2;u++){
    for(int v=-1;v<2;v++){
        red += oper[u+1][v+1]*GetRValue(srcBitmap->Canvas->Pixels[i+u][j+v]);
           green += oper[u+1][v+1]*GetGValue(srcBitmap->Canvas->Pixels[i+u][j+v]);
        blue += oper[u+1][v+1]*GetBValue(srcBitmap->Canvas->Pixels[i+u][j+v]);
    }
         }
       //以下六行程序确保得到的新颜色值在有效范围[0,255]之内
       red = red<0?0:red;
       red = red>255?255:red;
       green = green<0?0:green;
       green = green>255?255:green;
       blue = blue<0?0:blue;
       blue = blue>255?255:blue;
       bitmap->Canvas->Pixels[i][j] = (TColor)RGB(red,green,blue);
    }
        }
        //以下两个for循环用于重复边缘值
        for(int i=0;i<w;i++){
    bitmap->Canvas->Pixels[i][0]=srcBitmap->Canvas->Pixels[i][0];
    bitmap->Canvas->Pixels[i][h-1]=srcBitmap->Canvas->Pixels[i][h-1];
        }
        for(int j=1;j<h-1;j++){
    bitmap->Canvas->Pixels[0][j]=srcBitmap->Canvas->Pixels[0][j];
    bitmap->Canvas->Pixels[w-1][j]=srcBitmap->Canvas->Pixels[w-1][j];
        }
        dstBitmap->Assign(bitmap);
        delete bitmap;
    }
    =================================================================
    慢的原因在于你使用了bitmap->Canvas->Pixels。应该用bitmap->Canvas->ScanLine[j]得到第j行像素的起始地质,再加上一个偏移量得到一个点的像素值。
      

  2.   

    procedure TForm1.lktq(b1:Tbitmap);    //edge acquired
    var
       b0: Tbitmap;
       i, j: Integer;
       p1, p2, p3, p4: pbyteArray;
    begin
       b0 := Tbitmap.Create;
       b0.Assign(b1);      //Copies a b1 bitmap image to the bitmap  b0 object.
       b0.PixelFormat := pf24bit;
       b1.PixelFormat := pf24bit;      //24 bit
       for i := 1 to b0.Height - 2 do
       begin
          p1 := b0.ScanLine[i - 1];
          p2 := b0.ScanLine[i];
          p3 := b0.ScanLine[i + 1];    //scan b0 3 lines
          p4 := b1.ScanLine[i];
          for j := 1 to b0.Width - 2 do
          begin
             if (p2[3 * j + 2] = 0) and (p2[3 * j + 1] = 0) and (p2[3 * j] = 0) then
             begin            if ((p2[3 * (j - 1) + 2] = 0) and (p2[3 * (j - 1) + 1] = 0) and
                   (p2[3 * (j - 1)] = 0)) and       //pre line
                   ((p2[3 * (j + 1) + 2] = 0) and (p2[3 * (j + 1) + 1] = 0) and
                   (p2[3 * (j + 1)] = 0)) and       //next line            ((p1[3 * (j + 1) + 2] = 0) and (p1[3 * (j + 1) + 1] = 0) and
                   (p1[3 * (j + 1)] = 0)) and
                ((p1[3 * (j) + 2] = 0) and (p1[3 * (j) + 1] = 0) and (p1[3 * (j)]
                   = 0)) and
                ((p1[3 * (j - 1) + 2] = 0) and (p1[3 * (j - 1) + 1] = 0) and
                   (p1[3 * (j - 1)] = 0)) and            ((p3[3 * (j - 1) + 2] = 0) and (p3[3 * (j - 1) + 1] = 0) and
                   (p3[3 * (j - 1)] = 0)) and
                ((p3[3 * (j) + 2] = 0) and (p3[3 * (j) + 1] = 0) and (p3[3 * (j)]
                   = 0)) and
                ((p3[3 * (j + 1) + 2] = 0) and (p3[3 * (j + 1) + 1] = 0) and
                   (p3[3 * (j + 1)] = 0)) then     //0,0  to  2,2 nine points are black
                begin
                   p4[3 * j + 2] := 255;
                   p4[3 * j + 1] := 255;
                   p4[3 * j] := 255;        //while color
                end;
             end;
          end;
       end;
       b0.Free;
    end;
    这是针对256色黑白图片的轮廓提起,主要是判断每个黑点的周围八个点的颜色。也许你可以根据你的实际应用作相应的改动。感谢网友yan的帮助!!!
      

  3.   

    所谓轮廓提取就是掏空图形的内部点:如果原图中有一点为黑,且它的8个相邻点都是黑色时(此时该是内部点),则将该点删除。此时处理的虽然是二值图,但实际上是256级灰度图,不过只用到了0和255两种颜色。
    procedure TMyPicture.Button5Click(Sender: TObject);
    var
       b0, b1: Tbitmap;
       i, j: Integer;
       p1, p2, p3, p4: pbyteArray;
    begin
       b0 := Tbitmap.Create;
       b1 := Tbitmap.Create;
       b0.Assign(Image1.Picture.Bitmap);
       b1.Assign(Image1.Picture.Bitmap);
       b0.PixelFormat := pf24bit;
       b1.PixelFormat := pf24bit;
       for i := 1 to b0.Height - 2 do
       begin
          p1 := b0.ScanLine[i - 1];
          p2 := b0.ScanLine[i];
          p3 := b0.ScanLine[i + 1];
          p4 := b1.ScanLine[i];
          for j := 1 to b0.Width - 2 do
          begin
             if (p2[3 * j + 2] = 0) and (p2[3 * j + 1] = 0) and (p2[3 * j] = 0) then
             begin            if ((p2[3 * (j - 1) + 2] = 0) and (p2[3 * (j - 1) + 1] = 0) and
                   (p2[3 * (j - 1)] = 0)) and
                ((p2[3 * (j + 1) + 2] = 0) and (p2[3 * (j + 1) + 1] = 0) and
                   (p2[3 * (j + 1)] = 0)) and
                ((p1[3 * (j + 1) + 2] = 0) and (p1[3 * (j + 1) + 1] = 0) and
                   (p1[3 * (j + 1)] = 0)) and
                ((p1[3 * (j) + 2] = 0) and (p1[3 * (j) + 1] = 0) and (p1[3 * (j)]
                   = 0)) and
                ((p1[3 * (j - 1) + 2] = 0) and (p1[3 * (j - 1) + 1] = 0) and
                   (p1[3 * (j - 1)] = 0)) and
                ((p3[3 * (j - 1) + 2] = 0) and (p3[3 * (j - 1) + 1] = 0) and
                   (p3[3 * (j - 1)] = 0)) and
                ((p3[3 * (j) + 2] = 0) and (p3[3 * (j) + 1] = 0) and (p3[3 * (j)]
                   = 0)) and
                ((p3[3 * (j + 1) + 2] = 0) and (p3[3 * (j + 1) + 1] = 0) and
                   (p3[3 * (j + 1)] = 0)) then
                begin
                   p4[3 * j + 2] := 255;
                   p4[3 * j + 1] := 255;
                   p4[3 * j] := 255;
                end;
             end;      end;
          Image1.Picture.Bitmap.Assign(b1);
       end;
       b1.Free;
       b0.Free;
    end;