# openCV-python Basics
:::danger
Ubuntu
openCV-python
:::
- 主要按照官方指示進行安裝
> https://docs.opencv.org/2.4/doc/tutorials/introduction/linux_install/linux_install.html
- 安裝完測試
```python=
import cv2
image = cv2.imread("I:\\1.png")
(b,g,r) = image[0,0]#讀取(0,0)像素,opencv中圖像像素是BGR順序
print "red:%d,green:%d,blue:%d" %(r,g,b)#顯示像素值
image[0,0] = (100,150,200)#更改位置(0,0)像素值
(b,g,r) = image[0,0]#再次讀取
print "red:%d,green:%d,blue:%d" %(r,g,b)#顯示更改後的像素
corner = image[0:100,0:100]#讀取像素區塊
cv2.imshow("Corner",corner)#顯示像素區塊
image[0:100,0:100] = (0,255,255);#更改像素區塊
cv2.imshow("Updated",image)#顯示圖片
cv2.waitKey(0)#停止
```
- #### Basic Operations on Images
> https://docs.opencv.org/3.0-beta/doc/py_tutorials/py_core/py_basic_ops/py_basic_ops.html
- #### OpenCV-Python Tutorials
> https://docs.opencv.org/3.4.0/d6/d00/tutorial_py_root.html
---

- ## bilateral filter
> 濾波器有分為線性與非線性,其中雙邊濾波器(bilateral Filter)是屬於非線性,是一種可以去除
> 雜訊但同時可以保留圖像內容邊緣的濾波器,雙邊濾波器(bilateral Filter)與傳統的濾波器不同
> 在於雙邊濾波器(bilateral Filter)除了使用“幾何空間上的距離”決定係數之外,同時也考慮了在 像素之間的亮度值與色彩上來決定係數。 類似於高斯濾波器,雙邊濾波器也給每一個鄰域像素分配一個加權係數。這些加權係數包含兩個部 分,第一部分加權方式與高斯濾波一樣,第二部分的權重則取決於該鄰域像素與當前像素的灰度差 值。
> * 線性濾波:有一個有固定參數的核心,常見的有平均模糊(median Blurring)和高斯模糊 (Gaussian Blurring)。
> * 非線性濾波:沒有一個有固定的核心,常見的有中值濾波(mean filter)和雙邊濾波(bilateral filter)。
> bilateralFilter(src, dst, d, sigmaColor, sigmaSpace)
>
> src – Source 8-bit or floating-point, 1-channel or 3-channel image.
> dst – Destination image of the same size and type as src .
> d – Diameter of each pixel neighborhood that is used during filtering. If it is non-positive, it is computed from sigmaSpace .
> sigmaColor – Filter sigma in the color space. A larger value of the parameter means that farther colors within the pixel neighborhood (see sigmaSpace ) will be mixed together, resulting in larger areas of semi-equal color.
> sigmaSpace – Filter sigma in the coordinate space. A larger value of the parameter means that farther pixels will influence each other as long as their colors are close enough (see sigmaColor ). When d>0 , it specifies the neighborhood size regardless of sigmaSpace. Otherwise, d is proportional to sigmaSpace.
* d=13, sigmaColor=50, sigmaSpace=10
* d=5, sigmaColor=50, sigmaSpace=10
> - 比較兩組參數設定後的結果,由左到右分別為原圖,d=13,d=5得出結果圖
>
> 
> * 以上結果圖可以看出來d=13與d=5相比較時,d=13的鄰域像素被使用到的直徑較大,去除雜訊的效果也較明顯,一比較之下可以明顯從圖中看出來,所以在靜態且有大量雜訊需要去除的時候d參數的設定值可調高,因為flower.jpg輸入成灰階圖像較能看出差異,故輸入時就將圖轉換成灰階圖像。
> * 第一列圖:因為是灰階圖像可以看出d=13 filter的較為明顯,d=5與原圖比較還是看得出差異圖像稍微變平滑了。
> * 第二列圖:d=13時與原圖和d=5比較下大量的雜訊點都被去除了,d=13在圖像色彩上細看的話,可以看得出來色彩變得柔和(模糊)較不強烈。
> * 第三列圖:可以看出在d=13時圖像中的皺紋,已經看不太到了,但由於sigmaColor及sigmaSpace的值並不高,故圖像中看起來相當不協調,在d=5時還是看得出皺紋的存在,filter的效果並不佳。
> * 第四列圖:d=13時與原圖和d=5比較下大量的雜訊點都被去除了,d=13細看的話房子的色彩較淡了,天空的色彩也變淡了,d=5 filter完之後對比原圖是好了 一些。
> * 以上兩組參數filter後的六張圖,雖然兩組參數皆為sigmaColor=50, sigmaSpace=10,但在d的參數相差較多的情況下,還是能看得出來filter後照片的差異之處。
---
* d=13, sigmaColor=150, sigmaSpace=10
* d=13, sigmaColor=50, sigmaSpace=50
> - 比較兩組參數設定後的結果,由左到右分別為原圖, sigmaColor=150, sigmaSpace=10, sigmaColor=50, sigmaSpace=50 得出的結果圖。
> 
> * 以上結果圖可以看出來d=13的鄰域像素被使用到的直徑較大,去除雜訊的效果也較明顯,一比較之下可以明顯從圖中看出來,所以在靜態且有大量雜訊需要去除的時候d參數的設定值可調高,在這兩組參數中d的值是相同的,那麼圖像的變化取決於後面的sigmaColor及sigmaSpace
> * 可以看出sigmaColor和sigmaSpace的值,如果值較小(小於10),雙邊濾波的效果不明顯,如果值很大(大於150),雙邊濾波效果明顯,這時影像會被filter得非常平滑
> * 第一列圖:sigmaColor=150, sigmaSpace=10的圖,因為像素之間的亮度值與色彩的參數較大,玫瑰花一束因為色彩上差異不大所以在色彩的模糊上也較明顯,在空間的變化較不明顯,雖然花瓣的紋理都被模糊的看不清楚了,但花與花之間邊緣還是看得出來。
> * 第二列圖:sigmaColor=150, sigmaSpace=10的圖,大量雜訊都被去除了但看上去還是灰濛濛的,但如果再將sigmaSpace的值調高的話,整張圖會看起來相當不協調,雖然sigmaColor=50, sigmaSpace=50有將雜訊去除,但因為本身這張圖雜訊太大量了,很難filter到完美,所以這樣的效果已經算是不錯了。
> * 第三列圖:sigmaColor=150, sigmaSpace=10的圖,非常明顯皺紋都已經看不到了,整張圖有種過度朦朧感,眼睛的立體感都被filter掉了,sigmaColor=50, sigmaSpace=50雖然皺紋沒有完全消失,但眼睛的立體感還是在的,不會過於朦朧。
> * 第四列圖:sigmaColor=150, sigmaSpace=10的圖,大量的雜訊都沒filter掉了,在色彩上也像第三列圖一樣蒙上了一層朦朧感,看不出來圖像中人物的五官的立體感,sigmaColor=50, sigmaSpace=50雖雜訊沒有完全沒去除,但還是可以看出圖像大部分的雜訊都被去除了,並且圖像中人物的五官與色彩還是在正常範圍內的。
> * 以上兩組參數filter後的六張圖,雖然兩組參數皆為d=13,但在 sigmaColor及sigmaSpace的參數有相異的情況下,還是能看得出來filter後照片的差異之處,雙邊濾波會做保留邊緣的動作,也就是若顏色差異幅度太大,就會判定是邊緣而不模糊,若顏色差異幅度較小,就會進行模糊。
## Compare 2D bilateral filter with Gaussian filter, median filter and mean filter.
> 
> * 五張圖由左到右分別為原圖, bilateral, mean, median, Gaussian
> * median 如果filter很大的話,很容易將越大部分的中位數包起來,會將鄰居的點也包起來,就會變得一坨坨的。
- ## SIFT/SURE
> * 官方文件 https://docs.opencv.org/3.4.0/df/dd2/tutorial_py_surf_intro.html
> * 需要用到SURF與SIFT,在openCV 3.1.0之後的版本,不會在套件中,所以要使用的話,必須要額外去裝一個opencv_contrib libraries,才能使用裡面的cv2.xfeatures2d.SURF_create() & cv2.xfeatures2d.SIFT_create()
```python=
import numpy as np
import cv2
from matplotlib import pyplot as plt
MIN_MATCH_COUNT = 10 #設定最小match數量
#要match的兩張圖
img1 = cv2.imread('/mnt/hgfs/share/hw2/building_A.jpg',0) # queryImage
img2 = cv2.imread('/mnt/hgfs/share/hw2/building_B.jpg',0) # trainImage
# 要從xfeatures2d lib用SURF或SIFT找出特徵點
sift = cv2.xfeatures2d.SURF_create()
#cv2.xfeatures2d.SIFT_create() # SURF
# 特徵與描述點需要使用detectAndCompute獲得,函數將會回傳關鍵點與描述點,其中make為遮罩矩陣,用於圖片中的特定區域,將它設為None
kp1, des1 = sift.detectAndCompute(img1,None)
kp2, des2 = sift.detectAndCompute(img2,None)
#設定FLANN 其中search_params為搜尋的精確度,數值越高精確度越高,但相對時間也越久,index_params為決定tree數量以及演算法
FLANN_INDEX_KDTREE = 0
index_params = dict(algorithm = FLANN_INDEX_KDTREE, trees = 5)
search_params = dict(checks = 50)
#使用FlannBasedMatcher作為特徵匹配的方法,屬於暴力匹配法,其中FLANN演算法更快找到最鄰近的匹配特徵
flann = cv2.FlannBasedMatcher(index_params, search_params)
#用flann.knnMatch對每個匹配回傳回兩個最鄰近的描述,當第一個與第二個的匹配之間距離夠小時,才認為這是一個好的匹配
matches = flann.knnMatch(des1,des2,k=2)
# 先過濾matches出來的描述點好壞,如果距離*0.7大於原本的距離就加入到good的陣列裡
good = []
for m,n in matches:
if m.distance < 0.7*n.distance:
good.append(m)
#利用findHomography繪製描述範圍,如果找到的足夠的匹配數量(>10)則繪製,先將所有好的匹配對應點座標儲存
if len(good)>MIN_MATCH_COUNT:
src_pts = np.float32([ kp1[m.queryIdx].pt for m in good ]).reshape(-1,1,2)
dst_pts = np.float32([ kp2[m.trainIdx].pt for m in good ]).reshape(-1,1,2)
#有了M單位的矩陣
M, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC,5.0)
matchesMask = mask.ravel().tolist()
h,w = img1.shape
pts = np.float32([ [0,0],[0,h-1],[w-1,h-1],[w-1,0] ]).reshape(-1,1,2)
dst = cv2.perspectiveTransform(pts,M)
#透過perspectiveTransform回傳點的列表
img2 = cv2.polylines(img2,[np.int32(dst)],True,255,3, cv2.LINE_AA)
else:
print "Not enough matches are found - %d/%d" % (len(good),MIN_MATCH_COUNT)
matchesMask = None
draw_params = dict(matchColor = (0,255,0), # draw matches in green color
singlePointColor = None,
matchesMask = matchesMask, # draw only inliers
flags = 2)
#drawMatches主要用於繪製出匹配的兩個圖片的關鍵點並劃線
img3 = cv2.drawMatches(img1,kp1,img2,kp2,good,None,**draw_params)
plt.imshow(img3, 'gray'),plt.show()
```
- results
> 
###### tags: `opencv` `python`