1. 程式人生 > >dsp影象處理Prewitt運算元邊緣檢測

dsp影象處理Prewitt運算元邊緣檢測

——(完整工程檔案到我的資源下載)

Prewitt運算元邊緣檢測

一、實驗背景與意義

影象處理就是對資訊加工以滿足人的視覺心理或應用需求的方法。影象處理的方法有光學方法和電子學方法。從20世紀60年代起隨著電子計算機和計算技術的不斷提高和普及,數字影象處理進入了高速發展時期,而數字影象處理就是利用數字計算機或其它的硬體裝置對影象資訊轉換而得到的電訊號進行某些數學處理以提高影象的實用性。影象處理在遙感技術、醫學領域、安全領域,工業生產中有著廣泛的應用。其中在醫學應用中的超聲、核磁共振和CT等技術,安全領域和模式識別技術,工業中的無損檢測技術尤其引人注目。計算機進行影象處理一般有兩個目的:(1)生產更適合人觀察和識別的影象。(

2)希望能由計算機自動識別和理解影象。數字影象的邊緣檢測是影象分割、目標區域的識別、區域形狀提取等影象分析領域的重要基礎。影象處理分析的第一步往往就是邊緣檢測。物體的邊緣是以影象的區域性特徵不連續的形狀出現的,也就是指影象區域性亮度變化最顯著的部分,例如灰度值的突變、顏色的突變、紋理結構的突變等,同時物體的邊緣也是不同的區域分界處。影象邊緣有方向和幅度兩個特性,通常沿邊緣的走向灰度變化平緩,垂直於邊緣走向的畫素灰度變化劇烈。根據灰度變化的特點,影象邊緣可分為階躍型、房頂型和凸緣型。

邊緣檢測是影象處理、目標識別和計算機視覺等領域中最經典的研內容之一,已有較長的研究歷史,邊緣檢測是所有基於邊界分割方法的第一步。經典的邊緣檢測方法是對原始影象按畫素的某鄰域構造邊緣檢測運算元。應用邊緣檢測的演算法是基於邊界的分割方法,常用的邊緣檢測運算元有Roberts

SobelKirschPrewitt以及Laplace等。其中Prewitt運算元通過對影象進行八個方向的邊緣檢測,將其中方向響應最大的作為邊緣幅度影象的邊緣,且對噪聲具有平滑作用。傳統的邊緣檢測運算元的噪聲平滑能力和邊緣定位能力是矛盾的。為了克服這個不足,正確地得到影象的邊緣資訊,已經提出了很多方法,其中邊緣檢測和邊緣細化相結合可以有效地調節噪聲平滑和邊緣定位能力的矛盾。

二、基於Prewitt演算法邊緣檢測的原理

Prewitt運算元是一種一階微分運算元的邊緣檢測,利用畫素點上下、左右鄰點的灰度差,在邊緣處達到極值檢測邊緣,去掉部分偽邊緣,對噪聲具有平滑作用。其原理是在影象空間利用兩個方向模板與影象進行鄰域卷積來完成的,這兩個方向模板一個檢測水平邊緣,一個檢測垂直邊緣。

Prewitt邊緣檢測演算法是一種類似Sobel邊緣檢測演算法的邊緣模板演算法。Prewitt邊緣檢測運算元並不把重點放在相鄰的畫素上,它對噪聲具有平滑作用。採用3*3鄰域可以避免在畫素之間內插點上計算梯度。Prewitt運算元也是一種梯度幅值,該運算元包含兩組3*3的矩陣,分別為橫向及縱向,將之與影象作平面卷積,即可分別得出橫向及縱向的亮度差分近似值。如果以A代表原始影象,及分別代表經橫向及縱向邊緣檢測的影象,其模板的卷積因子如下:

  該運算元包含兩組3*3的矩陣,分別為橫向及縱向,將之與影象作平面卷積,即可分別得出橫向及縱向的亮度差分近似值。具體卷積演算法如下:

   經典Prewitt運算元認為:凡灰度新值大於或等於閾值的畫素點都是邊緣點。即選擇適當的閾值T,若G(i,j)≥T,則(i,j)為邊緣點,G(i,j)為邊緣影象。這種判定是欠合理的,會造成邊緣點的誤判,因為許多噪聲點的灰度值也很大,而且對於幅值較小的邊緣點,其邊緣反而丟失了。Prewitt運算元利用畫素點上下、左右鄰點灰度差,在邊緣處達到極值檢測邊緣。對噪聲具有平滑作用,定位精度不夠高。

三、演算法程式設計步驟

1、為了對影象利用Prewitt運算元進行邊緣檢測,程式設計主要步驟如下:

   輸入:原灰度影象sourceIMG;

   輸入:噪聲強度range;

輸出:加噪後的高斯噪聲影象resultIMG;

Step 1:獲取原影象的高rows與寬度cols;

Step 2:為輸出影象resultIMG申請空間;

Step 3:for ( i=0; i< cols*(rows-2) - 2; i++)

         取3*3模板對應的原始畫素;

         利用Prewitt垂直運算元和水平運算元計算相應差分並取絕對值輸出畫素=垂直方向差分+水平方向差分;

end for     

Step 4: 輸出影象resultIMG,程式結束。

2、C語言程式碼如下:

/* ======================================================================== */

/*  Copyright 2006 by Wintech Digital System Technology Corp.               */

/*  All rights reserved. Property of Texas Instruments Incorporated.        */

/*  Restricted rights to use, duplicate or disclose this code are           */

/*  granted through contract.                                             */

/* ======================================================================== */

/*========  標頭檔案引用===========*/

#include "stdio.h"

#include "math.h"

/*============= 工作變數定義======*/

unsigned char *pr_n;    //指標定義

unsigned char *pr_s;    //指標定義

//說明:定義資料存放變數

#pragma        DATA_SECTION(IMG,"data"); 

int  IMG[30000];

#pragma        DATA_SECTION(Noise_IMG,"data");

unsigned char  Noise_IMG[30000];

#pragma        DATA_SECTION(Smooth_IMG,"data");

unsigned char  Smooth_IMG[30000];

void  IMG_Smooth();

void IMG_sobel

(

    const unsigned char *restrict in,   /* Input image data   */

    unsigned char       *restrict out,  /* Output image data  */

    short cols, short rows              /* Image dimensions   */

);

///////////////////////////////////////////////////////////////////////////////////////////////////////////////

//使用說明:

//   1. 本程式可以在Simulator下運動;

//   2. 程式編譯、連結、載入成功後,先

//      執行File/data/load,將要進行顏色轉換的影象資料從RGB_peppers96x128.dat 

//     (說明:*.dat格式,內部存放了某影象各畫素的RGB顏色值)載入入資料儲存器儲存地址RGB_IMG中

//   3. 資料載入成功後,再Debug/Go Main, 一步一步執行程式

///////////////////////////////////////////////////////////////////////////////////////////////////////////////

int CoefArray[9]={1,1,1,1,1,1,1,1,1};

/*================= 主程式 ================*/

main()

{   

long n;

int imgH,imgW;

    int *ptr;

    imgH=160;  //影象高與寬,因為資料檔案中的影象是160X160畫素的

    imgW=160; 

/*=========== 初始化 ==========*/

    //1 把影象資料從IMG中移到Noise_IMG陣列中

    ptr=IMG;

    pr_n=Noise_IMG;

    for (n=0;n<imgH*imgW;n++)

       *pr_n++=*ptr++;

    //說明:在此暫停,可看到噪聲影象 

//指標指向陣列

pr_n=Noise_IMG;

pr_s=Smooth_IMG;

ptr=IMG;

    //2 呼叫子程式,進行彩色影象變換成灰度影象

    while (1)

    { 

       //IMG_Smooth(pr_n,pr_s,imgW,imgH);

       IMG_sobel(pr_n,pr_s,imgW,imgH);

       //說明:上面子程式執行後,在此暫停,可看平滑後的影象 

     }

    //說明:在此暫停,可看變換後的灰度影象 

}

/*============== 子程式 =============*/

void IMG_Smooth

(   unsigned char   *F,         /* 輸入帶有噪聲的灰度影象      */

    unsigned char   *G,         /* 輸出的平滑後的灰度影象      */

    int cols, int rows      /* 影象的寬度與高度            */

)

{    //定義區域性變數

    unsigned char *ptr, *pp, *newpp;

    int tmpNum,x, y,k,m,temp;

    int tmp[9];

    //影象四周的畫素不進釁交扔讜?

    for (x=0; x< cols -1; x++)  //處理第一行的畫素

         G[x] = F[x];

      //處理最後一行的畫素

      newpp  =  G + (rows-1)* cols;    //指標指向平滑影象

      pp     =  F+ (rows-1)* cols;     //指標指向噪聲影象        

      for (x=0; x< cols -1; x++) 

          * newpp++ = * pp++;

      //處理最左邊一列的畫素

      newpp  =  G;    //指標指向平滑影象

      pp     =  F;     //指標指向噪聲影象        

      for (y=0; y< rows -1; y++) 

      {

          *newpp = *pp;  

          newpp+=cols; pp+=cols;  //指標偏移到下一行畫素的位置

      }

      //處理最右邊一列的畫素

      newpp  =  G+cols;    //指標指向平滑影象

      pp     =  F+cols;     //指標指向噪聲影象        

      for (y=0; y< rows -1; y++) 

      {

         * newpp = * pp;  

         newpp+=cols; pp+=cols;  //指標偏移到下一行畫素的位置

      }

      //採用中值濾波的方式對影象中的每個畫素進行平滑

      for (y=1; y< rows -1; y++)

           for (x=1; x<cols -1; x++)

           {

                newpp   = G + y* cols +x;    //指標指向平滑影象

                pp      = F + y* cols +x;     //指標指向噪聲影象        

                //累加第一排的3個畫素的值

                ptr      =   pp-cols-1;             

                tmp[1]  =  (*ptr++)*CoefArray[0];

                tmp[2]=  (*ptr++)*CoefArray[1];

                tmp[3]=  (*ptr++)*CoefArray[2];

                //累加第二排的3個畫素的值

                ptr      = pp-1;             

                tmp[4]=  (*ptr++)*CoefArray[3];

                tmp[5]=  (*ptr++)*CoefArray[4];

                tmp[6]=  (*ptr++)*CoefArray[5];

                //累加第三排的3個畫素的值

                ptr      = pp+cols-1;             

                tmp[7]=  (*ptr++)*CoefArray[6];

                tmp[8]=  (*ptr++)*CoefArray[7];

                tmp[9]=  (*ptr++)*CoefArray[8];

               //累加的結果除以9

                tmpNum /=9;                      

               //檢測資料是否溢位,且將平均值賦給平滑影象

               if (tmpNum > 255)

                    *newpp=255;

               else

            {

               for(k=0;k<7;k++)

                  for(m=k+1;m<8;m++)

                   {

             if ( tmp[m]>tmp[m+1] )

                  {

                 temp=tmp[m];

                  tmp[m]=tmp[m+1];

                 tmp[m+1]=temp;

                   }

               }    

             *newpp=tmp[4];

          }

       //取排序好的陣列的中值賦給當前畫素

      // *newpp=tmp[4];

      // newpp++;                                

       //pp++;                                                   

}

} //程式結束

void IMG_sobel

(

    const unsigned char *restrict in,   /* Input image data   */

    unsigned char       *restrict out,  /* Output image data  */

    short cols, short rows              /* Image dimensions   */

)

{

    int H, O, V, i;

    int i00, i01, i02;

    int i10,      i12;

    int i20, i21, i22;

    int w = cols;

    /* -------------------------------------------------------------------- */

    /*  Iterate over entire image as a single, continuous raster line.      */

    /* -------------------------------------------------------------------- */

    for (i = 0; i < cols*(rows-2) - 2; i++)

    {

        /* ---------------------------------------------------------------- */

        /*  Read in the required 3x3 region from the input.                 */

        /* ---------------------------------------------------------------- */

        i00=in[i    ]; i01=in[i    +1]; i02=in[i    +2];

        i10=in[i+  w];                  i12=in[i+  w+2];

        i20=in[i+2*w]; i21=in[i+2*w+1]; i22=in[i+2*w+2];

        /* ---------------------------------------------------------------- */

        /*  Apply horizontal and vertical filter masks.  The final filter   */

        /*  output is the sum of the absolute values of these filters.      */

        /* ---------------------------------------------------------------- */

        H = -   i00 - 2*i01 -   i02 +

            +   i20 + 2*i21 +   i22;

        V = -   i00         +   i02

            - 2*i10         + 2*i12

            -   i20         +   i22;

        O = abs(H) + abs(V);

        /* ---------------------------------------------------------------- */

        /*  Clamp to 8-bit range.  The output is always positive due to     */

        /*  the absolute value, so we only need to check for overflow.      */

        /* ---------------------------------------------------------------- */

        if (O > 255) O = 255;

        else O = 0;

        /* ---------------------------------------------------------------- */

        /*  Store it.                                                       */

        /* ---------------------------------------------------------------- */

        out[i + 1] = O;

    }

}  

/* ======================================================================== */

/*             Copyright (c) 2012 LDX Digital System Technology Corp.   */

/*                         All Rights Reserved.                             */

/* ======================================================================== */

四、實驗步驟與結果

1、設定CCS 2.2工作在軟體模擬環境

(1)雙擊桌面上Setup CCS studio圖示,執行CCS Setup,進入CCS設定視窗;

(2)在出現的視窗中,按下圖所示的方法與順序進行CCS設定;

  

(3)在彈出的視窗中點選“是”按鍵儲存設定,退出CCS Setup,進入CCS開發環境,此時CCS被設定成Simulator模擬模式。

2、啟動CCS。

雙擊桌面上CCS 2 (C6000)圖示,執行CCS。

3、建立工程

(1)建立新的“BYJC”工程檔案

   選擇選單“Project”的“New…”項

彈出如下對話方塊:


輸入專案名稱BYJC後,點選完成即可。

3先新建源程式視窗:點選“File/New/Source File”,輸入原始碼(上一步已給出)

點選“File/Save”,在彈出的儲存對話方塊中,選擇儲存目錄為“BYJC”,選擇儲存型別為“C Source Files”,儲存源程式為main.c。

4. 執行程式,觀察試驗結果。

按如下方法觀看試驗結果:(1)編譯、連結程式:執行選單Project/Rebuild All,彙編結果在將彙編資訊輸出視窗中給出。編譯後將在Bebug目錄中產生一個ImgSmooth.out檔案。

2)載入程式:執行File/Load Program,選擇ImgSmooth.out並開啟,即將可執行檔案載入到DSP軟體模擬器simulator中,此時CCS將自動開啟一個反彙編視窗。

3)將RGB彩色影象的資料從dat檔案讀入到記憶體:執行File/data/load,將要進行顏色轉換的影象資料從Gray_Lenna160x160.dat (說明:*.dat格式,內部存放了某影象各畫素的RGB顏色值)檔案中載入入到資料儲存器,即在彈出的視窗中輸入儲存地址IMG與資料的長度,如下圖所示。


4)執行程式:執行Debug/Run。為了便於觀看試驗前後的結果,可以在程式中設定斷點,採用單步執行的方法執行程式。

5)顯示平滑前的噪聲影象:執行View/Graph/Image,在彈出的對話方塊中選擇顏色型別為RGB,並輸入RGB彩色影象三個通道資料的地址,以及影象顯示格式(顯示幾行、每行幾畫素)等內容,如下圖所示。這樣,原始的噪聲影象如圖1所示。



圖1 原始影象

(6)顯示平滑後的影象:執行View/Graph/Image,在彈出的對話方塊中選擇顏色型別為RGB,並輸入灰度影象據的地址,以及影象顯示格式(顯示幾行、每行幾畫素)等內容,如下圖所示。


圖二為Prewitt運算元邊緣檢測結果


五、分析與總結

  Prewitt運算元:利用畫素點上下、左右鄰點灰度差,在邊緣處達到極值檢測邊緣。對噪聲具有平滑作用,但定位精度不夠高。對噪聲有抑制作用,抑制噪聲的原理是通過畫素平均,但是畫素平均相當於對影象的低通濾波,所以Prewitt運算元對邊緣的定位不如Roberts運算元。影象的峰值處對應著影象的邊緣點,邊緣位置和導數(微分)間具有一定對應關係,可通過微分進行邊緣檢測。無噪聲時,可用Roberts運算元;Prewitt和Sobel運算元同時具有平均,即抑制噪聲作用;對階躍狀邊緣,Roberts得到的邊緣寬度≥1個畫素,Prewitt和Sobel運算元得到的邊緣寬度≥2個畫素。