# 視覺教學
### OpenCV install
```python
$ sudo apt update
$ sudo apt install libopencv-dev python3-opencv
```
#### verify installation
```python
$ python3 -c "import cv2; print(cv2.__version__)"
```
### OpenCV tutorial
```python
import cv2
import numpy as np
import matplotlib.pyplot as plt
```
#### read image from file
```python
image = cv2.imread('./ball1.jpg')
```
#### show image in window
```python
cv2.imshow('Image Window',image)
cv2.waitKey(0)
cv2.destroyAllWindows()
```
#### show image in pyplot
```python
def plot(image):
# cv2 reads image in BGR format, pyplot reads image in RGB format
RGB_image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
plt.imshow(RGB_image)
plt.show()
```
#### save image
```python
cv2.imwrite('./image/output.jpg', image)
```
#### image size
```python
image.shape[:] # returns (height,width,tunnel)
```
#### Connect with camera
```python
cap = cv2.VideoCapture(2) # choose camera index
while cap.isOpened():
# 從攝影機擷取一張影像
ret, img = cap.read()
cv2.imshow('image', img)
# 若 q 被按下則離開迴圈
if cv2.waitKey(1) & 0xFF == ord('q'):
cap.release() # 釋放攝影機
cv2.destroyAllWindows() # 關閉所有視窗
break
```
---
### Image processing
#### - Convert image to grayscale
```python
gray_image = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
```
#### - Gaussian Blur
Note: 做高斯模糊的圖片能夠去除很多圖片的雜訊,能更精準的找到輪廓。
```python
kernel_size = 17 # 進行高斯模糊時,對多大的範圍進行運算
blurred_image = cv2.GaussianBlur(image,(kernel_size,kernel_size),0)
```
---
## OpenCV Example
### Objective: Find location of ball
#### Method 1 : Canny edge detection
進行邊緣檢測
```python
def canny(image,low,high):
low_threshold = low
high_threshold = high
edges = cv2.Canny(image, low_threshold, high_threshold)
return edges
```
Note:
- 高於 high_threshold: 為 strong edge ,直接保留
- 低於 low_threshold: 不當作 edge
- 介於 low_threshold & high_threshold: 為 weak edge ,Canny會檢測 weak edge 是否能與 strong edge 相連,如果會相連的才會被保留。
#### Procedure
1. Convert image to grayscale
2. Gaussian blur
3. Canny detection
4. Find contours
```python
def canny_detection(image):
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blurred_image = cv2.GaussianBlur(gray_image, (21,21), 0)
canny_image = cv2.Canny(blurred_image,50,60)
plot(canny_image)
# find contours
contours, hierarchy = cv2.findContours(image=canny_image,mode=cv2.RETR_EXTERNAL,method=cv2.CHAIN_APPROX_NONE)
for contour in contours:
# gives area of contour
area = cv2.contourArea(contour)
# gives perimeter of contour
perimeter = cv2.arcLength(contour, closed=True)
# approximate boundaries for given polygon contour
borders = cv2.approxPolyDP(curve=contour,epsilon=0.1*perimeter,closed=True)
if len(borders)>3:
x, y, w, h = cv2.boundingRect(borders)
cv2.rectangle(image,(x,y),(x+w,h+y),(255,255,255),5) # draw rectangle borders of circle
centroid =(int(x+w/2),int(y+h/2))
cv2.circle(image, centroid ,1,(0,0,0),10) # draw center of circle
print("Centroid:" + str(centroid))
return image
```
```python
image = cv2.imread('./image/ball1.jpg')
img = canny_detection(image)
plot(img)
```
#### Method 2 : Hough Circle
#### Procedure
1. Convert image to grayscale
2. Gaussian blur
3. Canny detection (optional)
4. Apply Hough transform
```python
def hough(image):
# Convert to grayscale.
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blurred_image = cv2.GaussianBlur(gray_image, (17,17),0)
canny_image = cv2.Canny(blurred_image,80,95)
circles = cv2.HoughCircles(image=canny_image,method=cv2.HOUGH_GRADIENT,dp=1, minDist=30, param1 = 70,param2 = 30, minRadius = 40, maxRadius = 400)
if circles is not None:
# Convert the circle parameters x, y and r to integers.
circles = np.uint16(np.around(circles))
for circle in circles[0, :]:
x, y, r = circle[0], circle[1], circle[2]
# Draw the circumference of the circle.
cv2.circle(image, (x,y), r, (0, 0, 255), 7) # draw circumference of circle
cv2.circle(image, (x,y), 1, (0, 0, 255), 5) # draw center of circle
print("Centroid: "+str((a,b)))
return image
```
```python
image = cv2.imread('./image/ball1.jpg')
img = hough(image)
plot(img)
```