###### tags: `OpenCV`,`影像處理`,
# OpenCV 基礎篇-影像逐位元邏輯運算,濾波(filter)
**OpenCV常見的位元運算方法**
| 函數名稱 | 基本含義 |
| -------- | -------- |
|cv2.bitwise_and()|逐位元與(and) |
|cv2.bitwise_or() |逐位元或(or) |
|cv2.bitwise_xor()|逐位元互斥 |
|cv2.bitwise_not()| 逐位元 |
| 運算元1 | 運算元2 | 結果 | 規則 |
| -------| -------- | --- | -------- |
| 0 | 0 | 0 | and(0,0)=0 |
| 0 | 1 | 0 | and(0,1)=0 |
| 1 | 0 | 0 | and(1,0)=0 |
| 1 | 1 | 1 | and(1,1)=1 |
| 數值 | 十進位值 | 二進位值 |
| ---- | -------- | -------- |
| 數值1 | 198 | 1100 0110 |
| 數值2 | 219 | 1101 1011 |
| 逐位元與運算結果 | 194 | 1100 0010 |
| 2的次方 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
| ---- | ---- | --- | --- | --- | --- | --- | --- | -- |
| 數值 | 128 | 64 | 32 | 16 | 8 | 4 | 2 | 1
==>198 = 128+64+4+2=2的7次方+2的6次方+2的3次方+2的2次方
**與特殊值0和255逐位元與運算**
| 逐位元與運算 | 二進位值 |十進位值|二進位值 | 十進位值 |
| -----------| -------- | --- | ---- | --------|
| 數值N | 1101 1011 | 219 | 1101 1011 | 219 |
|特殊值(0或255)| 0000 0000 | 0 | 1111 1111 | 255 |
| 運算結果 | 0000 0000 | 0 | 1101 1011 | 219 |
:bulb:**說明**
數值219與數值0逐位元運算與得==>0
數值219與數值255逐位元運算與結果保持不變
```python=
import cv2
import numpy as np
a=np.random.randint(0,255,(5,5),dtype=np.uint8)
b=np.zeros((5,5),dtype=np.uint8) #設定b為mask,mask為0或255的相同矩陣
b[0:3,0:3]=255
b[4,4]=255
c=cv2.bitwise_and(a,b)
print("a=\n",a)
print("b=\n",b)
print("c=\n",c)
```
結果如下:

**圖像平滑處理**
* “平滑處理”(smoothing)也稱“模糊處理”(bluring)
* 是一項簡單且使用頻率很高的圖像處理方法
* 用途有很多,最常見的是用來減少圖像上的噪點或者失真
* 美肌處理
**影像濾波(Image Filter)**
* 就是在盡量保留圖像細節特徵的條件下對目標圖像的噪聲進行抑制
**均值濾波(Mean Filtering)**
* 均值濾波(低通濾波)是典型的線性濾波算法

其中紅色區域的像素值均值濾波處理過程為:
( (197+25+106+156+159)+ (149+40+107+5+71)+ (163+198+226+223+156)+(222+37+68+193+157)+ (42+72+250+41+75) ) / 25 = 125.52
其中5*5的矩陣稱為核Kernel
**cv2.blur**
blur(src, ksize, dst=None, anchor=None, borderType=None)
src 表待處理的輸入圖像
ksize 表示模糊內核大小。比如(1,15)表示生成的模糊內核是一個1*15的矩陣
dst 表示輸出與src相同大小和類型的圖像
anchor參數
borderType參數可忽略
核大小多以(寬度,高度)來表示,常用(3,3)或(5,5)表示

```python=
import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread('babynew.jpg') #我家女兒剛滿月時的照片
result = cv2.blur(img, (3, 3))
result1 = cv2.blur(img, (7, 7))#kernal越大實際越糊
#使用plt show圖
plt.rcParams['figure.figsize'] = [200, 100]
plt.rcParams['font.size'] = 150
img2 = cv2.cvtColor(img , cv2.COLOR_BGR2RGB)
plt.subplot(1,3,1)
plt.imshow(img2)
plt.xticks([]), plt.yticks([])
plt.title('origin image BGR') #Original
r2 = cv2.cvtColor(result , cv2.COLOR_BGR2RGB)
plt.subplot(1,3,2)
plt.imshow(r2)
plt.xticks([]), plt.yticks([])
plt.title('blur image k3') #kernal 3
r3 = cv2.cvtColor(result1 , cv2.COLOR_BGR2RGB)
plt.subplot(1,3,3)
plt.imshow(r3)
plt.xticks([]), plt.yticks([])
plt.title('blur image k7') #kernal 7
```

**均值濾波(Mean Filtering)**
優點:效率高缺點
缺點:它不能很好地保護圖像細節
在圖像去噪的同時也破壞了圖像的細節,從而使圖像變得模糊,不能很好地去除噪聲點,特別是椒鹽噪聲(白噪聲)。
**椒鹽噪聲(Salt Pepper Noise)**
椒鹽噪聲也稱為脈衝雜訊,是圖像中經常見到的一種雜訊,
它是一種隨機出現的白點或者黑點
**高斯濾波(高斯模糊)(Gaussian Filtering)**
簡而言之,非均一,有權重比例之分
<可參考維基百科 https://zh.wikipedia.org/zh-tw/%E9%AB%98%E6%96%AF%E6%A8%A1%E7%B3%8A>
下面兩張圖可以簡單呈現權重比例的分配,及運算概念




**雙邊濾波(Bilateral filter)**
除了像素在空間中位置遠近程度的影響,還考慮了像素亮度相近程度的影響。
特色: 雙邊濾波在濾波的同時能保證一定的邊緣信息,比高斯濾波更好的邊緣保留特性。
opencv提供的雙線性濾波器的加權計算包含2個部分
一部分叫做space-related bilateral filter coefficients空域參數,空域參數採用高斯核來計算。
一個是color-related bilateral filter coefficients 顏色域參數,顏色域參數是基於像素與中心像素的亮度的差值的加權,相似的像素賦給較大的權值,不相似的賦給較小的權值,處理完的圖像更像一個水彩畫,可用於圖像分割,但是運行較慢。

**cv2.bilateralFilter**
bilateralFilter(src, d, sigmaColor, sigmaSpace, dst=None, borderType=None)
src:待處理的輸入圖像
d參數:表示在過濾期間使用的每個像素鄰域的直徑
sigmaColor:參數表示色彩空間的標準方差,一般盡可能大。
較大的參數值意味著像素鄰域內較遠的顏色會混合在一起,而產生更大面積的半相等顏色。
如果sigmaColor沒輸入,則sigmaColor由sigmaSpace計算得出。
sigmaSpace參數表示坐標空間的標準方差(像素單位),一般盡可能小。
參數值越大意味著只要它們的顏色足夠接近,越遠的像素都會相互影響。
當d > 0時,它指定鄰域大小而不考慮sigmaSpace。d與sigmaSpace成正比。
```python=
import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread('babynew.jpg')
blurResult = cv2.blur(img, (5, 5)) #均值濾波
gaussianBlurResult = cv2.GaussianBlur(img, (5, 5), 0) #高斯濾波
bilateralResult = cv2.bilateralFilter(img, d=0, sigmaColor=50 ,sigmaSpace=10) #雙邊濾波
plt.rcParams['figure.figsize'] = [200, 100]
plt.rcParams['font.size'] = 150
img2 = cv2.cvtColor(img , cv2.COLOR_BGR2RGB)
plt.subplot(1,4,1)
plt.imshow(img2)
plt.xticks([]), plt.yticks([])
plt.title('origin image BGR')
blurResult2 = cv2.cvtColor(blurResult , cv2.COLOR_BGR2RGB)
plt.subplot(1,4,2)
plt.imshow(blurResult2)
plt.xticks([]), plt.yticks([])
plt.title('blur image ')
gaussianBlurResult2 = cv2.cvtColor(gaussianBlurResult , cv2.COLOR_BGR2RGB)
plt.subplot(1,4,3)
plt.imshow(gaussianBlurResult2)
plt.xticks([]), plt.yticks([])
plt.title('gaussianBlurResult image ')
bilateralResult2 = cv2.cvtColor(bilateralResult , cv2.COLOR_BGR2RGB)
plt.subplot(1,4,4)
plt.imshow(bilateralResult2)
plt.xticks([]), plt.yticks([])
plt.title('bilateralResult image ')
```

**這毫無疑問就是美肌開下去啦**
高斯濾波看起來比較協調
雙邊濾波看筆來邊緣就很明顯
**再拿之前惡搞小孩在美金圖片來試試**
```python=
import cv2
import numpy as np
import matplotlib.pyplot as plt
newnew_photo=cv2.imread("result_dollar_new.bmp",0)
blurResult = cv2.blur(newnew_photo, (5, 5))
gaussianBlurResult = cv2.GaussianBlur(newnew_photo, (5, 5), 0)
bilateralResult = cv2.bilateralFilter(newnew_photo, d=0, sigmaColor=40, sigmaSpace=5)
plt.rcParams['figure.figsize'] = [200, 100]
plt.rcParams['font.size'] = 150
img = cv2.cvtColor(newnew_photo , cv2.COLOR_BGR2RGB)
plt.subplot(1,4,1)
plt.imshow(img)
plt.xticks([]), plt.yticks([])
plt.title('origin image BGR')
blurResult2 = cv2.cvtColor(blurResult , cv2.COLOR_BGR2RGB)
plt.subplot(1,4,2)
plt.imshow(blurResult2)
plt.xticks([]), plt.yticks([])
plt.title('blur image ')
gaussianBlurResult2 = cv2.cvtColor(gaussianBlurResult , cv2.COLOR_BGR2RGB)
plt.subplot(1,4,3)
plt.imshow(gaussianBlurResult2)
plt.xticks([]), plt.yticks([])
plt.title('gaussianBlurResult image ')
bilateralResult2 = cv2.cvtColor(bilateralResult , cv2.COLOR_BGR2RGB)
plt.subplot(1,4,4)
plt.imshow(bilateralResult2)
plt.xticks([]), plt.yticks([])
plt.title('bilateralResult image ')
```
**灰階照片就沒彩色照片效果來的明顯**

**中值濾波函數(MedianBlur)**
中值濾波是一種非線性數字濾波器技術,經常用於去除圖像或者其他信號中的噪聲,是處理椒鹽噪聲的常用降噪算法。
在使用鄰域平均法去噪的同時,也會讓邊界變得模糊。而中值濾波是非線性的圖像處理方法,在去噪的同時可以兼顧到邊界信息的保留。
**cv2.medianBlur**
medianBlur(src, ksize, dst=None)
src參數表示待處理的輸入圖像。
size參數表示濾波窗口尺寸,必須是奇數並且大於1。
比如這裡是5,中值濾波器就會使用5×5的範圍來計算。
dst參數表示輸出與src相同大小和類型的圖像。
**有請Lena**
```python=
#評比哪個濾波對於處理白噪聲最優秀
import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread('lenaNoise.png')#有請白噪聲的lena
blurResult = cv2.blur(img, (5, 5)) #均值濾波
gaussianBlurResult = cv2.GaussianBlur(img, (5, 5), 0)#高斯濾波
bilateralResult = cv2.bilateralFilter(img, d=0, sigmaColor=100, sigmaSpace=15)#雙邊濾波
medianResult = cv2.medianBlur(img, 5)#中值濾波
plt.rcParams['figure.figsize'] = [150, 200]
plt.rcParams['font.size'] = 150
img2 = cv2.cvtColor(img , cv2.COLOR_BGR2RGB)
plt.subplot(2,3,1)
plt.imshow(img2)
plt.xticks([]), plt.yticks([])
plt.title('origin image BGR')
blurResult2 = cv2.cvtColor(blurResult , cv2.COLOR_BGR2RGB)
plt.subplot(2,3,2)
plt.imshow(blurResult2)
plt.xticks([]), plt.yticks([])
plt.title('blur image ')
gaussianBlurResult2 = cv2.cvtColor(gaussianBlurResult , cv2.COLOR_BGR2RGB)
plt.subplot(2,3,3)
plt.imshow(gaussianBlurResult2)
plt.xticks([]), plt.yticks([])
plt.title('gaussianBlurResult image ')
bilateralResult2 = cv2.cvtColor(bilateralResult , cv2.COLOR_BGR2RGB)
plt.subplot(2,3,4)
plt.imshow(bilateralResult2)
plt.xticks([]), plt.yticks([])
plt.title('bilateralResult image ')
medianResult2 = cv2.cvtColor(medianResult , cv2.COLOR_BGR2RGB)
plt.subplot(2,3,5)
plt.imshow(medianResult2)
plt.xticks([]), plt.yticks([])
plt.title('medianResult image ')
```
登愣~~~~~~


結論就是連我ㄚ罵都看的出來啊!!
**中值濾波完勝,把lena處理的好美ㄚ**