---
# System prepended metadata

title: Open CV  三小時基礎
tags: [自己加油]

---

# Open CV  三小時基礎
# [作者的github](https://github.com/murtazahassan/Learn-OpenCV-in-3-hours/blob/master/chapter8.py)
# [影片連結](https://www.youtube.com/watch?v=WQeoO7MI0Bs&t=5543s)
###### tags: `自己加油`
## Ch1
### Read Images Videos and Webcams

解析圖片的是幾格* 幾格的架構，如下圖
![](https://i.imgur.com/gXEZ7qU.png)

舉例來說，"3"這個數字在10* 10的顯示方式可以用下圖來代表
![](https://i.imgur.com/nq1zStt.png)

規格 px * px 
VGA = 640 * 480
HD = 1280 * 720
FHD = 1920 * 1080
4K = 3840 * 2160

#### gray
Binary Image 
![](https://i.imgur.com/77dvoDb.png)
this is a 2 levels image
0 = black
1 = white

![](https://i.imgur.com/QaGW3Hw.png)
More levels mean more clear
levels 就是黑到白分成幾階
目前總共會有0-255的分別
套用在RGB也是一樣用0-255來調整顏色
![](https://i.imgur.com/ve2DU7D.png)
所以我們可以稱呼
![](https://i.imgur.com/TFNsD8h.png)
這張圖片是"8bits" 或是 "256Levels"

#### RGB
![](https://i.imgur.com/I7fwdV0.png)
可以看到合在一起就是原圖

![](https://i.imgur.com/feD2UNH.png)
RGB套用到VGA 裡面，就會有640 * 480 * 3

接下來是一個簡單的印出灰階圖片的程式
```python=
import cv2

img = cv2.imread("C:\\Users\\User\\Downloads\\IMG20210607233134.jpg")
#讓cv讀取圖片，括號裡面打檔案path
#圖片尺寸要挑好
#檔案路徑要用\\或/

imgGray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
#把img的RGB轉成GRAY

cv2.imshow("Gray Image",imgGray)
#"Gray Image"是顯示的圖片的名稱
#imgGray檔案

cv2.waitKey(0)
```

Blur 處理
```python=
import cv2

img = cv2.imread("C:\\Users\\User\\Desktop\\test.png")

imgGray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
#把img的RGB轉成GRAY

imgBlur = cv2.GaussianBlur(imgGray,(7,7),0)
#7,7是ksize(kernal size)，會模糊化
#0是sigmaX ，調X軸的標準差


cv2.imshow("Blur Image",imgBlur)
#印降解析後的
cv2.imshow("Gray Image",imgGray)
#印灰階的
cv2.waitKey(0)
```
blur前
![](https://i.imgur.com/Jf3CWgO.png)
blur後
![](https://i.imgur.com/OMb4Ycz.png)

```python=
import cv2

img = cv2.imread("C:\\Users\\User\\Desktop\\test.png")

imgCanny = cv2.Canny(img,700,700)
imgCanny2 = cv2.Canny(img,15,20)
#Canny採用雙閾值
#​設置的閾值過高，可能會漏掉重要信息
#閾值過低，將會把枝節信息看得很重要。

cv2.imshow("Canny Image",imgCanny)
cv2.imshow("Canny2 Image",imgCanny2)

cv2.waitKey(0)
```
閾值適當
![](https://i.imgur.com/nSawpfF.png)
閾值過低
![](https://i.imgur.com/KDeUzdU.png)


<hr>

## Ch2
### Basic Functions
座標化
![](https://i.imgur.com/ZSBnXWP.png)

```python=
import cv2
import numpy as np

img = cv2.imread("C:\\Users\\User\\Desktop\\test.png")
kernel = np.ones((5,5),np.uint8)
#有符號: int8, int16, int32, int64
#無符號: uint8, uint16, uint32, uint64
#依據平台自動對應上面的其中一個，例如在32位元系統和64位元系統上使用int的長度就會不同

imgCanny = cv2.Canny(img,700,700)
imgDialation = cv2.dilate(imgCanny,kernel,iterations=1)#迭代一次
#迭代會重複執行，逐漸接近目標


cv2.imshow("Dialation Image",imgDialation)


cv2.waitKey(0)
```
dilate後
![](https://i.imgur.com/u2N5f4C.png)
用途1：Dilation 影像膨脹通常是配合著影像侵蝕 Erosion 使用，先使用侵蝕的方式使影像中的線條變窄，同時也去除雜訊，之後再透過 Dilation 將影像膨脹回來。
用途2：用來連接兩個很靠近但分開的物體。

```python=
import cv2
import numpy as np

img = cv2.imread("C:\\Users\\User\\Desktop\\test.png")
kernel = np.ones((5,5),np.uint8)
#有符號: int8, int16, int32, int64
#無符號: uint8, uint16, uint32, uint64
#依據平台自動對應上面的其中一個，例如在32位元系統和64位元系統上使用int的長度就會不同

imgCanny = cv2.Canny(img,700,700)
imgDialation = cv2.dilate(imgCanny,kernel,iterations=1)#迭代一次
imgErode = cv2.erode(imgDialation,kernel,iterations=1)

cv2.imshow("Dialation Image",imgDialation)
cv2.imshow("ErodeImage",imgErode)


cv2.waitKey(0)
```
Erode後
![](https://i.imgur.com/fgdbeoc.png)

用途1：Erosion 影像侵蝕對於移除影像中的小白雜點很有幫助，可用來去噪，例如影像中的小雜點，雜訊。
用途2：細化影像，消除毛刺。





<hr>

## Ch3
### Resizing and Cropping

```python=
import cv2
import numpy as np

img = cv2.imread("C:\\Users\\User\\Desktop\\test.png")
print(img.shape)
#以 cv2.imread 讀進來的資料，會儲存成一個 NumPy 的陣列
#此 NumPy 陣列的前兩個維度分別是圖片的高度與寬度，第三個維度則是圖片的 channel（RGB 彩色圖片的 channel 是 3，灰階圖片則為 1）。

imgResize = cv2.resize(img,(300,200))

cv2.imshow("ErodeImage",img)
cv2.imshow("imgResize",imgResize)

cv2.waitKey(0)
```
Numpy array更改
(221,228,3)
![](https://i.imgur.com/UGc2EAV.png)

(300,200)
![](https://i.imgur.com/1Gd82zg.png)

```python=
import cv2
import numpy as np

img = cv2.imread("C:\\Users\\User\\Desktop\\test.png")

imgCropped = img[0:300,200:500]
# 裁切區域的 x 與 y 座標（左上角）
#x = 100
#y = 100

# 裁切區域的長度與寬度
#w = 250
#h = 150

# 裁切圖片
#crop_img = img[y:y+h, x:x+w]

cv2.imshow("ErodeImage",img)
cv2.imshow("imgCropped",imgCropped)

cv2.waitKey(0)
```
before
![](https://i.imgur.com/72uJOBP.png)
after
![](https://i.imgur.com/USJNyi3.png)

<hr>

## Ch4
### Shapes and Text
```python=
import cv2
import numpy as np

img = np.zeros((512,512,3),np.uint8)
#zero = black
#512,512 means size (px)


print(img)
#print 很多frame
#print出的frame代表RGB三層的DATA
#目前的圖片是全黑，所以三層都是[0 0 0]
#順序BGR
#所以調成[255 0 0]
img[0:200,200:500]=255,0,0#就會是blue
#加上一個blue的mask
#[]內是尺寸
#如果寫img[:]=255,0,0
#就會全覆蓋

cv2.line(img,(0,0),(300,300),(0,255,0),3)
#放在img上
#start (0,0)
#end (300,300)
#color (0,255,0)
#thickness 3

cv2.line(img,(0,0),(img.shape[1],img.shape[0]),(255,0,0),3)
#img.shape[1] --> weigh
#img.shape[0] --> heigh
#跟著圖片大小做縮放

cv2.rectangle(img,(0,0),(150,250),(0,0,255),3)
#如果thickness欄位改成cv2.FILLED，效果是填滿

cv2.circle(img,(150,250),50,(0,255,255),3)
#起始點(150,250)
#半徑50

cv2.putText(img,"test",(150,300),cv2.FONT_HERSHEY_TRIPLEX,1,(0,150,150),2)
#顯示test
#起始點(150,300)
#font = cv2.FONT_HERSHEY_TRIPLEX
#scale = 1
#color
#thickness

print(img.shape)
#print (512,512)

cv2.imshow("Image",img)
cv2.waitKey(0)
```

加上一個藍色mask
![](https://i.imgur.com/0xFPRDi.png)

加上線條
![](https://i.imgur.com/mF2xAwb.png)

另一種方法畫線
![](https://i.imgur.com/4sQ7lqT.png)

正方形
![](https://i.imgur.com/6xMAPpx.png)

圓
![](https://i.imgur.com/nxjM1WY.png)

Text
![](https://i.imgur.com/GPvrgPD.png)







<hr>

## Ch5
### Warp Prespective

範例圖片
![](https://i.imgur.com/HZy5r2w.png)

```python=
import cv2
import numpy as np

img = cv2.imread("C:\\Users\\User\\Desktop\\cards.jpg")

width,height = 250,350

pts1 = np.float32([[111,219],[287,188],[154,482],[352,440]])
#four points value -->use paint open the image
#訂出圖片的四角座標來做其他調整

pts2 = np.float32([[0,0],[width,0],[0,height],[width,height]])
#width,height 要另外定義

matrix = cv2.getPerspectiveTransform(pts1,pts2)
#透視變換matrix
#input:  欲顯示片段的四點座標 , 轉換視角後的座標

imgOutput = cv2.warpPerspective(img,matrix,(width,height))
#要有matrix才能做變換

cv2.imshow("Image",img)
cv2.imshow("o Image",imgOutput)



cv2.waitKey(0)
```

得到圖片座標
用小畫家開啟圖片，游標的位置會顯示x,y的px(畫面左下角)
![](https://i.imgur.com/t8C5Tlp.png)

output
#圖片座標跟影片中不一樣，請用小畫家來確認座標
![](https://i.imgur.com/yyGRqU6.png)
[參考 透視變換](https://blog.csdn.net/guduruyu/article/details/72518340)

<hr>

## Ch6
### Joining Images

```python=
import cv2
import numpy as np

img = cv2.imread("C:\\Users\\User\\Desktop\\test.png")

imgHor = np.hstack((img,img))
#水平

imgVer = np.vstack((img,img))
#垂直

cv2.imshow("Horizontal",imgHor)
cv2.imshow("Vertical",imgVer)

cv2.waitKey(0)
```
兩張圖片顯示在一個視窗
水平
![](https://i.imgur.com/tTGwKjy.png)
垂直
![](https://i.imgur.com/tGrJYID.png)

同時顯示gray跟BGR的function
```python=
import cv2
import numpy as np

img = cv2.imread("C:\\Users\\User\\Desktop\\test.png")

#請去github複製
def stackImages(scale,imgArray):
    rows = len(imgArray)
    cols = len(imgArray[0])
    rowsAvailable = isinstance(imgArray[0], list)
    width = imgArray[0][0].shape[1]
    height = imgArray[0][0].shape[0]
    if rowsAvailable:
        for x in range ( 0, rows):
            for y in range(0, cols):
                if imgArray[x][y].shape[:2] == imgArray[0][0].shape [:2]:
                    imgArray[x][y] = cv2.resize(imgArray[x][y], (0, 0), None, scale, scale)
                else:
                    imgArray[x][y] = cv2.resize(imgArray[x][y], (imgArray[0][0].shape[1], imgArray[0][0].shape[0]), None, scale, scale)
                if len(imgArray[x][y].shape) == 2: imgArray[x][y]= cv2.cvtColor( imgArray[x][y], cv2.COLOR_GRAY2BGR)
        imageBlank = np.zeros((height, width, 3), np.uint8)
        hor = [imageBlank]*rows
        hor_con = [imageBlank]*rows
        for x in range(0, rows):
            hor[x] = np.hstack(imgArray[x])
        ver = np.vstack(hor)
    else:
        for x in range(0, rows):
            if imgArray[x].shape[:2] == imgArray[0].shape[:2]:
                imgArray[x] = cv2.resize(imgArray[x], (0, 0), None, scale, scale)
            else:
                imgArray[x] = cv2.resize(imgArray[x], (imgArray[0].shape[1], imgArray[0].shape[0]), None,scale, scale)
            if len(imgArray[x].shape) == 2: imgArray[x] = cv2.cvtColor(imgArray[x], cv2.COLOR_GRAY2BGR)
        hor= np.hstack(imgArray)
        ver = hor
    return ver

imgGray= cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)    
#這個function可以同時處理gray跟BGR


imgStack = stackImages(0.5,([img,img,img],[imgGray,img,img]))
#調用stackImage
#兩個輸入值
#scale 0.5
#row ,column 隨意調整

cv2.imshow("imgStack",imgStack)

cv2.waitKey(0)
```
包含gray跟BGR的stack
![](https://i.imgur.com/tKxaNGU.png)



<hr>

## Ch7
### Color Detection

HSV即色相、飽和度、明度

```python=
import cv2
import numpy as np

img = cv2.imread("C:\\Users\\User\\Desktop\\test.png")

imgHSV= cv2.cvtColor(img,cv2.COLOR_BGR2HSV)

cv2.imshow("imgHSV",imgHSV)

cv2.waitKey(0)
```
HSV後
![](https://i.imgur.com/5UDZ3B2.png)

```python=
import cv2
import numpy as np

path = ("C:\\Users\\User\\Desktop\\test.png")
img = cv2.imread(path)

def empty(a):
    pass

cv2.namedWindow("TrackBars")
cv2.resizeWindow("TrackBars",640,240)
cv2.createTrackbar("Hue Min","TrackBars",0,179,empty)
cv2.createTrackbar("Hue Max","TrackBars",179,179,empty)
cv2.createTrackbar("Sat Min","TrackBars",0,255,empty)
cv2.createTrackbar("Sat Max","TrackBars",255,255,empty)
cv2.createTrackbar("Val Min","TrackBars",0,255,empty)
cv2.createTrackbar("Val Max","TrackBars",255,255,empty)
#0是起始值
#179是最大值

while True:
    img = cv2.imread(path)
    imgHSV= cv2.cvtColor(img,cv2.COLOR_BGR2HSV)
    h_min = cv2.getTrackbarPos("Hue Min","TrackBars")
    h_max = cv2.getTrackbarPos("Hue Max","TrackBars")
    s_min = cv2.getTrackbarPos("Sat Min","TrackBars")
    s_max = cv2.getTrackbarPos("Sat Max","TrackBars")
    v_min = cv2.getTrackbarPos("Val Min","TrackBars")
    v_max = cv2.getTrackbarPos("Val Max","TrackBars")
    print(h_min,h_max,s_min,s_max,v_min,v_max)
    lower = np.array([h_min,s_min,v_min])
    upper = np.array([h_max,s_max,v_max])
    mask = cv2.inRange(imgHSV,lower, upper)
    cv2.imshow("imgHSV",imgHSV)
    cv2.imshow("mask",mask)
    cv2.waitKey(1)
```
建立一個bar來調整HSV
![](https://i.imgur.com/22UaI4Z.png)
建立一個mask來顯示調整成果
![](https://i.imgur.com/UsXrdR6.png)
這是調整V min的成果
![](https://i.imgur.com/5FEfRoU.png)

```python=
import cv2
import numpy as np

path = ("C:\\Users\\User\\Desktop\\test.png")
img = cv2.imread(path)

def stackImages(scale,imgArray):
    rows = len(imgArray)
    cols = len(imgArray[0])
    rowsAvailable = isinstance(imgArray[0], list)
    width = imgArray[0][0].shape[1]
    height = imgArray[0][0].shape[0]
    if rowsAvailable:
        for x in range ( 0, rows):
            for y in range(0, cols):
                if imgArray[x][y].shape[:2] == imgArray[0][0].shape [:2]:
                    imgArray[x][y] = cv2.resize(imgArray[x][y], (0, 0), None, scale, scale)
                else:
                    imgArray[x][y] = cv2.resize(imgArray[x][y], (imgArray[0][0].shape[1], imgArray[0][0].shape[0]), None, scale, scale)
                if len(imgArray[x][y].shape) == 2: imgArray[x][y]= cv2.cvtColor( imgArray[x][y], cv2.COLOR_GRAY2BGR)
        imageBlank = np.zeros((height, width, 3), np.uint8)
        hor = [imageBlank]*rows
        hor_con = [imageBlank]*rows
        for x in range(0, rows):
            hor[x] = np.hstack(imgArray[x])
        ver = np.vstack(hor)
    else:
        for x in range(0, rows):
            if imgArray[x].shape[:2] == imgArray[0].shape[:2]:
                imgArray[x] = cv2.resize(imgArray[x], (0, 0), None, scale, scale)
            else:
                imgArray[x] = cv2.resize(imgArray[x], (imgArray[0].shape[1], imgArray[0].shape[0]), None,scale, scale)
            if len(imgArray[x].shape) == 2: imgArray[x] = cv2.cvtColor(imgArray[x], cv2.COLOR_GRAY2BGR)
        hor= np.hstack(imgArray)
        ver = hor
    return ver

def empty(a):
    pass

cv2.namedWindow("TrackBars")
cv2.resizeWindow("TrackBars",640,240)
cv2.createTrackbar("Hue Min","TrackBars",0,179,empty)
cv2.createTrackbar("Hue Max","TrackBars",179,179,empty)
cv2.createTrackbar("Sat Min","TrackBars",0,255,empty)
cv2.createTrackbar("Sat Max","TrackBars",255,255,empty)
cv2.createTrackbar("Val Min","TrackBars",100,255,empty)
cv2.createTrackbar("Val Max","TrackBars",255,255,empty)
#0是起始值
#179是最大值

while True:
    img = cv2.imread(path)
    imgHSV= cv2.cvtColor(img,cv2.COLOR_BGR2HSV)
    h_min = cv2.getTrackbarPos("Hue Min","TrackBars")
    h_max = cv2.getTrackbarPos("Hue Max","TrackBars")
    s_min = cv2.getTrackbarPos("Sat Min","TrackBars")
    s_max = cv2.getTrackbarPos("Sat Max","TrackBars")
    v_min = cv2.getTrackbarPos("Val Min","TrackBars")
    v_max = cv2.getTrackbarPos("Val Max","TrackBars")
    #print(h_min,h_max,s_min,s_max,v_min,v_max)
    lower = np.array([h_min,s_min,v_min])
    upper = np.array([h_max,s_max,v_max])
    mask = cv2.inRange(imgHSV,lower, upper)
   
    
    imgResult = cv2.bitwise_and(img,img,mask=mask)
    
    cv2.imshow("img",img)
    cv2.imshow("imgHSV",imgHSV)
    cv2.imshow("mask",mask)
    cv2.imshow("result",imgResult)
    
    imgStack = stackImages(0.6,([img,imgHSV],[mask,imgResult]))
    
    cv2.imshow("stack",imgStack)
    
        #如果按下ESC键，就退出
    if cv2.waitKey(10) == 27:
       break

#關閉所有視窗
cv2.destroyAllWindows()
```
把四張圖放上同一個stack
![](https://i.imgur.com/dkKjxLI.png)
調整bar的值也可以同步調整stack的圖


<hr>

## Ch8
### Contour / Shape Detection

範例圖片
![](https://i.imgur.com/6go22uR.png)
```python=
import cv2
import numpy as np

def stackImages(scale,imgArray):
    rows = len(imgArray)
    cols = len(imgArray[0])
    rowsAvailable = isinstance(imgArray[0], list)
    width = imgArray[0][0].shape[1]
    height = imgArray[0][0].shape[0]
    if rowsAvailable:
        for x in range ( 0, rows):
            for y in range(0, cols):
                if imgArray[x][y].shape[:2] == imgArray[0][0].shape [:2]:
                    imgArray[x][y] = cv2.resize(imgArray[x][y], (0, 0), None, scale, scale)
                else:
                    imgArray[x][y] = cv2.resize(imgArray[x][y], (imgArray[0][0].shape[1], imgArray[0][0].shape[0]), None, scale, scale)
                if len(imgArray[x][y].shape) == 2: imgArray[x][y]= cv2.cvtColor( imgArray[x][y], cv2.COLOR_GRAY2BGR)
        imageBlank = np.zeros((height, width, 3), np.uint8)
        hor = [imageBlank]*rows
        hor_con = [imageBlank]*rows
        for x in range(0, rows):
            hor[x] = np.hstack(imgArray[x])
        ver = np.vstack(hor)
    else:
        for x in range(0, rows):
            if imgArray[x].shape[:2] == imgArray[0].shape[:2]:
                imgArray[x] = cv2.resize(imgArray[x], (0, 0), None, scale, scale)
            else:
                imgArray[x] = cv2.resize(imgArray[x], (imgArray[0].shape[1], imgArray[0].shape[0]), None,scale, scale)
            if len(imgArray[x].shape) == 2: imgArray[x] = cv2.cvtColor(imgArray[x], cv2.COLOR_GRAY2BGR)
        hor= np.hstack(imgArray)
        ver = hor
    return ver


def getContours(img):#define a function named "getContours"
    countours,hierarchy = cv2.findContours(img,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE)
    for cnt in countours:
        area = cv2.contourArea(cnt)
        print(area)
        
    

path = ("C:\\Users\\User\\Desktop\\shape.png")
img = cv2.imread(path)

imgGray = cv2.cvtColor(img,cv2.COLOR_RGB2GRAY)
imgBlur = cv2.GaussianBlur(imgGray,(7,7),1)
imgCanny = cv2.Canny(imgBlur,50,50)
getContours(imgCanny)

imgStack = stackImages(0.6,([img,imgGray,imgBlur],[imgCanny,img,img]))


cv2.imshow("Stack",imgStack)
cv2.waitKey(0)


```
算出area
![](https://i.imgur.com/lTl0uWU.png)


```python=
import cv2
import numpy as np

def stackImages(scale,imgArray):
    rows = len(imgArray)
    cols = len(imgArray[0])
    rowsAvailable = isinstance(imgArray[0], list)
    width = imgArray[0][0].shape[1]
    height = imgArray[0][0].shape[0]
    if rowsAvailable:
        for x in range ( 0, rows):
            for y in range(0, cols):
                if imgArray[x][y].shape[:2] == imgArray[0][0].shape [:2]:
                    imgArray[x][y] = cv2.resize(imgArray[x][y], (0, 0), None, scale, scale)
                else:
                    imgArray[x][y] = cv2.resize(imgArray[x][y], (imgArray[0][0].shape[1], imgArray[0][0].shape[0]), None, scale, scale)
                if len(imgArray[x][y].shape) == 2: imgArray[x][y]= cv2.cvtColor( imgArray[x][y], cv2.COLOR_GRAY2BGR)
        imageBlank = np.zeros((height, width, 3), np.uint8)
        hor = [imageBlank]*rows
        hor_con = [imageBlank]*rows
        for x in range(0, rows):
            hor[x] = np.hstack(imgArray[x])
        ver = np.vstack(hor)
    else:
        for x in range(0, rows):
            if imgArray[x].shape[:2] == imgArray[0].shape[:2]:
                imgArray[x] = cv2.resize(imgArray[x], (0, 0), None, scale, scale)
            else:
                imgArray[x] = cv2.resize(imgArray[x], (imgArray[0].shape[1], imgArray[0].shape[0]), None,scale, scale)
            if len(imgArray[x].shape) == 2: imgArray[x] = cv2.cvtColor(imgArray[x], cv2.COLOR_GRAY2BGR)
        hor= np.hstack(imgArray)
        ver = hor
    return ver


def getContours(img):
    countours,hierarchy = cv2.findContours(img,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE)
    for cnt in countours:
        area = cv2.contourArea(cnt)
        print(area)
        cv2.drawContours(imgContour,cnt,-1,(255,0,0),3)
        #contour index =-1，means draw all the contours
        #thickness =3
path = ("C:\\Users\\User\\Desktop\\shape.png")
img = cv2.imread(path)
imgContour = img.copy()

imgGray = cv2.cvtColor(img,cv2.COLOR_RGB2GRAY)
imgBlur = cv2.GaussianBlur(imgGray,(7,7),1)
imgCanny = cv2.Canny(imgBlur,50,50)
getContours(imgCanny)

imgStack = stackImages(0.6,([img,imgCanny,imgContour]))



cv2.imshow("Stack",imgStack)
cv2.waitKey(0)


```
用area來draw
![](https://i.imgur.com/H1r3rNI.png)

```python=
import cv2
import numpy as np

def stackImages(scale,imgArray):
    rows = len(imgArray)
    cols = len(imgArray[0])
    rowsAvailable = isinstance(imgArray[0], list)
    width = imgArray[0][0].shape[1]
    height = imgArray[0][0].shape[0]
    if rowsAvailable:
        for x in range ( 0, rows):
            for y in range(0, cols):
                if imgArray[x][y].shape[:2] == imgArray[0][0].shape [:2]:
                    imgArray[x][y] = cv2.resize(imgArray[x][y], (0, 0), None, scale, scale)
                else:
                    imgArray[x][y] = cv2.resize(imgArray[x][y], (imgArray[0][0].shape[1], imgArray[0][0].shape[0]), None, scale, scale)
                if len(imgArray[x][y].shape) == 2: imgArray[x][y]= cv2.cvtColor( imgArray[x][y], cv2.COLOR_GRAY2BGR)
        imageBlank = np.zeros((height, width, 3), np.uint8)
        hor = [imageBlank]*rows
        hor_con = [imageBlank]*rows
        for x in range(0, rows):
            hor[x] = np.hstack(imgArray[x])
        ver = np.vstack(hor)
    else:
        for x in range(0, rows):
            if imgArray[x].shape[:2] == imgArray[0].shape[:2]:
                imgArray[x] = cv2.resize(imgArray[x], (0, 0), None, scale, scale)
            else:
                imgArray[x] = cv2.resize(imgArray[x], (imgArray[0].shape[1], imgArray[0].shape[0]), None,scale, scale)
            if len(imgArray[x].shape) == 2: imgArray[x] = cv2.cvtColor(imgArray[x], cv2.COLOR_GRAY2BGR)
        hor= np.hstack(imgArray)
        ver = hor
    return ver


def getContours(img):
    countours,hierarchy = cv2.findContours(img,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE)
    for cnt in countours:
        area = cv2.contourArea(cnt)
        print(area)
        if area>500:
            cv2.drawContours(imgContour,cnt,-1,(255,0,0),3)
        #contour index =-1，means draw all the contours
        #thickness =3
            peri = cv2.arcLength(cnt,True)
            print(peri)
        #印出length
            approx = cv2.approxPolyDP(cnt,0.02*peri,True)
            print(approx)
        #印出圖形的point
path = ("C:\\Users\\User\\Desktop\\shape.png")
img = cv2.imread(path)
imgContour = img.copy()

imgGray = cv2.cvtColor(img,cv2.COLOR_RGB2GRAY)
imgBlur = cv2.GaussianBlur(imgGray,(7,7),1)
imgCanny = cv2.Canny(imgBlur,50,50)
getContours(imgCanny)

imgStack = stackImages(0.6,([img,imgCanny,imgContour]))



cv2.imshow("Stack",imgStack)
cv2.waitKey(0)


```
知道圖形的area，lenght，point
![](https://i.imgur.com/YIbi4zo.png)

```python=
import cv2
import numpy as np

def stackImages(scale,imgArray):
    rows = len(imgArray)
    cols = len(imgArray[0])
    rowsAvailable = isinstance(imgArray[0], list)
    width = imgArray[0][0].shape[1]
    height = imgArray[0][0].shape[0]
    if rowsAvailable:
        for x in range ( 0, rows):
            for y in range(0, cols):
                if imgArray[x][y].shape[:2] == imgArray[0][0].shape [:2]:
                    imgArray[x][y] = cv2.resize(imgArray[x][y], (0, 0), None, scale, scale)
                else:
                    imgArray[x][y] = cv2.resize(imgArray[x][y], (imgArray[0][0].shape[1], imgArray[0][0].shape[0]), None, scale, scale)
                if len(imgArray[x][y].shape) == 2: imgArray[x][y]= cv2.cvtColor( imgArray[x][y], cv2.COLOR_GRAY2BGR)
        imageBlank = np.zeros((height, width, 3), np.uint8)
        hor = [imageBlank]*rows
        hor_con = [imageBlank]*rows
        for x in range(0, rows):
            hor[x] = np.hstack(imgArray[x])
        ver = np.vstack(hor)
    else:
        for x in range(0, rows):
            if imgArray[x].shape[:2] == imgArray[0].shape[:2]:
                imgArray[x] = cv2.resize(imgArray[x], (0, 0), None, scale, scale)
            else:
                imgArray[x] = cv2.resize(imgArray[x], (imgArray[0].shape[1], imgArray[0].shape[0]), None,scale, scale)
            if len(imgArray[x].shape) == 2: imgArray[x] = cv2.cvtColor(imgArray[x], cv2.COLOR_GRAY2BGR)
        hor= np.hstack(imgArray)
        ver = hor
    return ver


def getContours(img):
    countours,hierarchy = cv2.findContours(img,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE)
    for cnt in countours:
        area = cv2.contourArea(cnt)
        print(area)
        if area>500:
            cv2.drawContours(imgContour,cnt,-1,(255,0,0),3)
        #contour index =-1，means draw all the contours
        #thickness =3
            peri = cv2.arcLength(cnt,True)
            print(peri)
        #印出length
            approx = cv2.approxPolyDP(cnt,0.02*peri,True)
            print(approx)
            objCor = len(approx)
            x,y,w,h = cv2.boundingRect(approx)
            cv2.rectangle(imgContour,(x,y),(x+w,y+h),(255,0,0),2)
            
            
            
path = ("C:\\Users\\User\\Desktop\\shape.png")
img = cv2.imread(path)
imgContour = img.copy()

imgGray = cv2.cvtColor(img,cv2.COLOR_RGB2GRAY)
imgBlur = cv2.GaussianBlur(imgGray,(7,7),1)
imgCanny = cv2.Canny(imgBlur,50,50)
getContours(imgCanny)

imgStack = stackImages(0.6,([img,imgCanny,imgContour]))



cv2.imshow("Stack",imgStack)
cv2.waitKey(0)


```
知道approx 的長度，用方形框起來
![](https://i.imgur.com/A9YFtUA.png)

```python=
import cv2
import numpy as np

def stackImages(scale,imgArray):
    rows = len(imgArray)
    cols = len(imgArray[0])
    rowsAvailable = isinstance(imgArray[0], list)
    width = imgArray[0][0].shape[1]
    height = imgArray[0][0].shape[0]
    if rowsAvailable:
        for x in range ( 0, rows):
            for y in range(0, cols):
                if imgArray[x][y].shape[:2] == imgArray[0][0].shape [:2]:
                    imgArray[x][y] = cv2.resize(imgArray[x][y], (0, 0), None, scale, scale)
                else:
                    imgArray[x][y] = cv2.resize(imgArray[x][y], (imgArray[0][0].shape[1], imgArray[0][0].shape[0]), None, scale, scale)
                if len(imgArray[x][y].shape) == 2: imgArray[x][y]= cv2.cvtColor( imgArray[x][y], cv2.COLOR_GRAY2BGR)
        imageBlank = np.zeros((height, width, 3), np.uint8)
        hor = [imageBlank]*rows
        hor_con = [imageBlank]*rows
        for x in range(0, rows):
            hor[x] = np.hstack(imgArray[x])
        ver = np.vstack(hor)
    else:
        for x in range(0, rows):
            if imgArray[x].shape[:2] == imgArray[0].shape[:2]:
                imgArray[x] = cv2.resize(imgArray[x], (0, 0), None, scale, scale)
            else:
                imgArray[x] = cv2.resize(imgArray[x], (imgArray[0].shape[1], imgArray[0].shape[0]), None,scale, scale)
            if len(imgArray[x].shape) == 2: imgArray[x] = cv2.cvtColor(imgArray[x], cv2.COLOR_GRAY2BGR)
        hor= np.hstack(imgArray)
        ver = hor
    return ver


def getContours(img):
    countours,hierarchy = cv2.findContours(img,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE)
    for cnt in countours:
        area = cv2.contourArea(cnt)
        print(area)
        if area>500:
            cv2.drawContours(imgContour,cnt,-1,(255,0,0),3)
        #contour index =-1，means draw all the contours
        #thickness =3
            peri = cv2.arcLength(cnt,True)
            print(peri)
        #印出length
            approx = cv2.approxPolyDP(cnt,0.02*peri,True)
            print(approx)
            objCor = len(approx)
            x,y,w,h = cv2.boundingRect(approx)
            
            #設定一個object，如果邊數=3，印出tri
            if objCor == 3:ObjectType = "Tri"
            else:ObjectType = "None"
            cv2.rectangle(imgContour,(x,y),(x+w,y+h),(255,0,0),2)
            cv2.putText(imgContour,ObjectType,(x+(w//2)-10,y+(h//2)-10),cv2.FONT_HERSHEY_COMPLEX,0.5,(0,255,0),2)
                                                #Text要顯示在圖形的哪裡
            
path = ("C:\\Users\\User\\Desktop\\shape.png")
img = cv2.imread(path)
imgContour = img.copy()

imgGray = cv2.cvtColor(img,cv2.COLOR_RGB2GRAY)
imgBlur = cv2.GaussianBlur(imgGray,(7,7),1)
imgCanny = cv2.Canny(imgBlur,50,50)
getContours(imgCanny)

imgStack = stackImages(0.6,([img,imgCanny,imgContour]))



cv2.imshow("Stack",imgStack)
cv2.waitKey(0)


```
判斷邊數來顯示字
![](https://i.imgur.com/AiJKcNZ.png)

```python=
import cv2
import numpy as np

def stackImages(scale,imgArray):
    rows = len(imgArray)
    cols = len(imgArray[0])
    rowsAvailable = isinstance(imgArray[0], list)
    width = imgArray[0][0].shape[1]
    height = imgArray[0][0].shape[0]
    if rowsAvailable:
        for x in range ( 0, rows):
            for y in range(0, cols):
                if imgArray[x][y].shape[:2] == imgArray[0][0].shape [:2]:
                    imgArray[x][y] = cv2.resize(imgArray[x][y], (0, 0), None, scale, scale)
                else:
                    imgArray[x][y] = cv2.resize(imgArray[x][y], (imgArray[0][0].shape[1], imgArray[0][0].shape[0]), None, scale, scale)
                if len(imgArray[x][y].shape) == 2: imgArray[x][y]= cv2.cvtColor( imgArray[x][y], cv2.COLOR_GRAY2BGR)
        imageBlank = np.zeros((height, width, 3), np.uint8)
        hor = [imageBlank]*rows
        hor_con = [imageBlank]*rows
        for x in range(0, rows):
            hor[x] = np.hstack(imgArray[x])
        ver = np.vstack(hor)
    else:
        for x in range(0, rows):
            if imgArray[x].shape[:2] == imgArray[0].shape[:2]:
                imgArray[x] = cv2.resize(imgArray[x], (0, 0), None, scale, scale)
            else:
                imgArray[x] = cv2.resize(imgArray[x], (imgArray[0].shape[1], imgArray[0].shape[0]), None,scale, scale)
            if len(imgArray[x].shape) == 2: imgArray[x] = cv2.cvtColor(imgArray[x], cv2.COLOR_GRAY2BGR)
        hor= np.hstack(imgArray)
        ver = hor
    return ver


def getContours(img):
    countours,hierarchy = cv2.findContours(img,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE)
    for cnt in countours:
        area = cv2.contourArea(cnt)
        print(area)
        if area>500:
            cv2.drawContours(imgContour,cnt,-1,(255,0,0),3)
        #contour index =-1，means draw all the contours
        #thickness =3
            peri = cv2.arcLength(cnt,True)
            print(peri)
        #印出length
            approx = cv2.approxPolyDP(cnt,0.02*peri,True)
            print(approx)
            objCor = len(approx)
            x,y,w,h = cv2.boundingRect(approx)
            
            #設定一個object，如果邊數=3，印出tri
            if objCor == 3:ObjectType = "Tri"
            elif objCor == 4:
                aspRatio = w/float(h)
                if aspRatio >0.95 and aspRatio <1.05 :ObjectType="Square"
                else:ObjectType = "Rectangle"
            elif objCor > 4:ObjectType = "Circle"
            else:ObjectType = "None"
            cv2.rectangle(imgContour,(x,y),(x+w,y+h),(255,0,0),2)
            cv2.putText(imgContour,ObjectType,(x+(w//2)-10,y+(h//2)-10),cv2.FONT_HERSHEY_COMPLEX,0.5,(0,255,0),2)
                                                #Text要顯示在圖形的哪裡
            
path = ("C:\\Users\\User\\Desktop\\shape.png")
img = cv2.imread(path)
imgContour = img.copy()

imgGray = cv2.cvtColor(img,cv2.COLOR_RGB2GRAY)
imgBlur = cv2.GaussianBlur(imgGray,(7,7),1)
imgCanny = cv2.Canny(imgBlur,50,50)
getContours(imgCanny)

imgStack = stackImages(0.6,([img,imgCanny,imgContour]))



cv2.imshow("Stack",imgStack)
cv2.waitKey(0)


```
用if elif else ，判定圖形名稱
![](https://i.imgur.com/wPtSGXA.png)


<hr>

## Ch9
### Face Detection

```mermaid
graph LR
A[Positives Faces] --> B[Train] --> D[XML File]
C[Negatives Non Faces] -->B
```

```python=
import cv2
import numpy as np   

faceCascade = cv2.CascadeClassifier("C:\\Users\\User\\Desktop\\haarcascade_frontalface_default.xml")
#
path = ("C:\\Users\\User\\Desktop\\lena.jpg")
img = cv2.imread(path)
呼叫model
imgGray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

faces = faceCascade.detectMultiScale(imgGray,1.1,4)

for (x,y,w,h) in faces:
    cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2)


cv2.imshow("Result", img)
cv2.waitKey(0)


```
人臉辨識
![](https://i.imgur.com/8K5W6OT.png)


<hr>


## Projects1
### Virtual Paint
## Projects2
### Paper Scanner
## Projects3
### Number Plate Detector
