2015年12月16日 星期三

資工三乙 02360386 柯明男 HW4

作業內容:Filter

Smoothing Spatial Filter (平滑空間濾波器):

讓影像模糊化(平滑化,去銳利化)
原理:減少與周圍的差距 遵循以下比例 把周為的點還有自己都加起來 然後除16

圖1.平滑的遮罩

小問題:當遇到邊邊該怎麼辦

我的作法是 當遇到邊邊 利如(-1,-1) ,(-1,0),(-1,1),(0,-1),(1,-1) 就直接跳過
而這樣也會相對的 最後要除的數字多寡
另外 因為怕會因為修改前面而影響到後面 所以 我有被分一份原始圖片
程式嗎如下:
        unsigned char mask[3][3] = {{1,2,1},{2,4,2},{1,2,1}};
        int maskSum;
        int Sum[3];
        BYTE **bPtrImageRow = new BYTE*[iImageHeight]; // 原始圖片的2維陣列宣告
        for(int j=0; j<iImageHeight; j++)
        {
            bPtrImageRow[j] = (Byte *)Image2->Picture->Bitmap->ScanLine[j];
        }
        for(int i=0; i<iImageHeight; i++)
        {
            BYTE *bPtrImage2Row = (Byte *)Image4->Picture->Bitmap->ScanLine[i];
            //要修改圖片的宣告

            for(int j=0; j<iImageWidth; j++)
            {
                maskSum=0;//計算最後要除的量
                Sum[0]=0;//B
                Sum[1]=0;//G
                Sum[2]=0;//R
                for(int h=0;h<3;h++)
                {
                    for(int w=0;w<3;w++)
                    {
                        //防止出界
                        if((i-1+h)>=0 && (i-1+h)<iImageHeight && (j-1+w)>=0 && (j-1+w)<iImageWidth)
                        {
                            for(int k=0;k<3;k++)
                            Sum[k]+=bPtrImageRow[i-1+h][(j-1+w)*3+k]*mask[h][w];
                            maskSum+=mask[h][w];
                        }
                    }
                }
                for(int k=0;k<3;k++)
                    bPtrImage2Row[j*3+k]=Sum[k]/maskSum;
            }
        }
圖2.平滑的效果 稍為可以看出有比較模糊一點

Sharping Spatial Filter(銳化空間濾波器)

讓影像的邊邊可以更明顯 
原裡:增加與周圍的差距
圖3.銳化的遮罩

小問題:有可能會超過 0,255 其他基本上沒問題

程式碼如下:
        Image4->Picture=Image2->Picture;
        int Sum[3];
        BYTE **bPtrImageRow = new BYTE*[iImageHeight];
        for(int j=0; j<iImageHeight; j++)
        {
            bPtrImageRow[j] = (Byte *)Image2->Picture->Bitmap->ScanLine[j];
        }
        for(int i=0; i<iImageHeight; i++)
        {
            BYTE *bPtrImage2Row = (Byte *)Image4->Picture->Bitmap->ScanLine[i];
            for(int j=0; j<iImageWidth; j++)
            {
                Sum[0]=0;//B
                Sum[1]=0;//G
                Sum[2]=0;//R
                for(int h=0;h<3;h++)
                {
                    for(int w=0;w<3;w++)
                    {
                        if((i-1+h)>=0 && (i-1+h)<iImageHeight && (j-1+w)>=0 && (j-1+w)<iImageWidth)
                        {
                            for(int k=0;k<3;k++)
                            Sum[k]+=(bPtrImageRow[i][j*3+k]-bPtrImageRow[i-1+h][(j-1+w)*3+k]);
                        }
                    }
                }
                for(int k=0;k<3;k++)
                {//防止超過0,255 另外這裡多加1次 是因為上面只+8次
                    if(Sum[k]+bPtrImageRow[i][j*3+k]<0)
                        bPtrImage2Row[j*3+k]=0;
                    else if(Sum[k]+bPtrImageRow[i][j*3+k]>255)
                        bPtrImage2Row[j*3+k]=255;
                    else
                        bPtrImage2Row[j*3+k]=Sum[k]+bPtrImageRow[i][j*3+k];
                }
            }
        }
圖4.銳化的效果 Lenna的帽子跟頭髮都比較明顯了

Median Filter(中值濾波器)

去除圖片的雜訊
原裡:雜訊通常是圖片中 較為極端的點
而中值濾波器 是去3*3裡面的中位數 可以去除較為極端的點

小問題:怎麼找中位數(好像也是不是問題

        Image4->Picture=Image2->Picture;
        BYTE **bPtrImageRow = new BYTE*[iImageHeight];
        vector<vector<int> >temp(3,vector<int>());//二維的vector宣告 
        for(int j=0; j<iImageHeight; j++)
        {
            bPtrImageRow[j] = (Byte *)Image2->Picture->Bitmap->ScanLine[j];
        }
        for(int i=0; i<iImageHeight; i++)
        {
            BYTE *bPtrImage2Row = (Byte *)Image4->Picture->Bitmap->ScanLine[i];
            for(int j=0; j<iImageWidth; j++)
            {
                temp[0].clear();//清除vector的內容
                temp[1].clear();
                temp[2].clear();
                for(int h=0;h<3;h++)
                {
                    for(int w=0;w<3;w++)
                    {
                        if((i-1+h)>=0 && (i-1+h)<iImageHeight && (j-1+w)>=0 && (j-1+w)<iImageWidth)
                        {
                            for(int k=0;k<3;k++)
                            //將數字丟進vector最後面
                            temp[k].push_back(bPtrImageRow[i-1+h][(j-1+w)*3+k]);
                        }
                    }
                }
                for(int k=0;k<3;k++)
                {
                    sort(temp[k].begin(),temp[k].end()); //將3個vector 排序
                    if(temp[k].size()%2) //當是奇數值 中位數就是正中間的那個數字
                    {
                        bPtrImage2Row[j*3+k] = temp[k][temp[k].size()/2];
                    }
                    else //偶數時 則是把中間的兩個數相加除二
                    {
                        bPtrImage2Row[j*3+k] = (temp[k][temp[k].size()/2]+temp[k][temp[k].size()/2-1])/2;
                    }
                }
            }
        }
內鍵sort(陣列頭,陣列尾) 要include <algorithm>還要 using namespace std;
以下是灑入雜訊的程式碼:
        int num=StrToInt(Edit5->Text);
        BYTE **bPtrImageRow = new BYTE*[iImageHeight];
        for(int j=0; j<iImageHeight; j++)
        {
            bPtrImageRow[j] = (Byte *)Image2->Picture->Bitmap->ScanLine[j];
        }
        for(int i=0; i<iImageHeight; i++)
        {
            for(int j=0; j<iImageWidth; j++)
            {
                if(rand()%100<num/2)
                {
                    for(int k=0;k<3;k++)
                        bPtrImageRow[i][j*3+k]=0; //灑白點
                }
                if(rand()%100>=100-num/2)
                {
                    for(int k=0;k<3;k++)
                        bPtrImageRow[i][j*3+k]=255; //灑黑點
                }
            }
        }
        Image2->Refresh();//如果沒有打會看不出已經灑點了!!
圖5.灑6%雜訊 去雜訊的效果非常的好
圖6.灑20%雜訊 去雜訊效果也是非常好 不過此時可以很明顯看出有雜訊
程式碼:點我

沒有留言:

張貼留言