作業內容: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%雜訊 去雜訊效果也是非常好 不過此時可以很明顯看出有雜訊
程式碼:點我
沒有留言:
張貼留言