# Python學習筆記 0006 (圖像轉正、鼠標打點)
## 建立數組、打點
```javascript=
import cv2
import numpy as np
img = cv2.imread("img2.jpg")
pts1 = np.int32 ([[978, 404],[1907, 80],[1025, 593],[1916, 365]])//設定一個32位元的正整數
print(pts1)
print(pts1[0][0],pts1[0][1])
cv2.circle(img, (int(pts1[x][0]), int(pts1[x][1])), 10 ,(0 , 0 , 255), cv2.FILLED)
cv2.imshow("img", img)
cv2.waitKey(0)
```
- (int(pts1[x][0]), int(pts1[x][1]))
這裡需要用正整數
[[ 978. 404.]
[1907. 80.]
[1025. 593.]
[1916. 365.]]
978 404

## 用for迴圈 自動讀取打點
```javascript=
import cv2
import numpy as np
img = cv2.imread("img2.jpg")
pts1 = np.float32 ([[978, 404],[1450, 210],[1025, 593],[1530, 480]])
for x in range (0,4):
cv2.circle(img, (int(pts1[x][0]), int(pts1[x][1])), 5 ,(0 , 0 , 255), cv2.FILLED)
cv2.imshow("img", img)
cv2.waitKey(0)
```
## 圖形拉正
```javascript=
import cv2
import numpy as np
img = cv2.imread("img2.jpg")
width, height = 350,250
pts1 = np.float32 ([[978, 404],[1450, 210],[1025, 593],[1530, 480]])
pts2 = np.float32 ([[0, 0],[width, 0],[0, height], [width, height]])
matrix = cv2.getPerspectiveTransform(pts1, pts2)//這個需要用浮點數
imgOutput = cv2.warpPerspective(img, matrix, (width,height))
for x in range (0,4):
cv2.circle(img, (int(pts1[x][0]), int(pts1[x][1])), 5 ,(0 , 0 , 255), cv2.FILLED)
cv2.imshow("img", img)
cv2.imshow("imgOutput", imgOutput)
cv2.waitKey(0)
```

## 鼠標打點
```javascript=
import cv2
#import numpy as np
img = cv2.imread('img2.jpg')
cv2.imshow("img", img)
def mousePoints(event,x,y, flags, param):
if event == cv2.EVENT_LBUTTONDOWN:
print(x,y)
cv2.setMouseCallback("img", mousePoints)
cv2.waitKey(0)
```
click img 上的任一點即會出現該點的XY座標

## 鼠標打點+圖形拉正
```javascript=
import cv2
import numpy as np
def mousePoints(event,x,y, flags, param):
if event == cv2.EVENT_LBUTTONDOWN:
print(x,y)
img = cv2.imread("img2.jpg")
width, height = 350,250
pts1 = np.float32 ([[978, 404],[1450, 210],[1025, 593],[1530, 480]])
pts2 = np.float32 ([[0, 0],[width, 0],[0, height], [width, height]])
matrix = cv2.getPerspectiveTransform(pts1, pts2)
imgOutput = cv2.warpPerspective(img, matrix, (width,height))
cv2.imshow("imgOutput", imgOutput)
for x in range (0,4):
cv2.circle(img, (int(pts1[x][0]), int(pts1[x][1])), 5 ,(0 , 0 , 255), cv2.FILLED)
cv2.imshow("img", img)
cv2.setMouseCallback("img", mousePoints)
cv2.waitKey(0)
```

## 儲存鼠標,click XY
接下來要儲存點的(XY)
```javascript=
import cv2
import numpy as np
circles = np.zeros((4,2),np.float)//設置陣列4*2
counter = 0
def mousePoints(event,x,y, flags, param):
global counter
if event == cv2.EVENT_LBUTTONDOWN:
circles[counter] = x,y
counter = counter + 1
print(circles)
img = cv2.imread("img2.jpg")
cv2.imshow("img", img)
cv2.setMouseCallback("img", mousePoints)
cv2.waitKey(0)
6.png
![Uploading file..._5z0plwqs1]()
![Uploading file..._smgkrgk71]()
```
## 建立LOOP
因為陣列只能存取四次資料(Click point)
接下來需要建立 while迴圈給他跑
```javascript=
import cv2
import numpy as np
circles = np.zeros((4,2),np.float)
counter = 0
def mousePoints(event,x,y, flags, param):
global counter
if event == cv2.EVENT_LBUTTONDOWN:
circles[counter] = x,y
counter = counter + 1
print(circles)
img = cv2.imread("img2.jpg")
while True:
if counter == 4:
width, height = 350,250
pts1 = np.float32 ([[circles[0]],[circles[1]],[circles[2]],[circles[3]]])
pts2 = np.float32 ([[0, 0],[width, 0],[0, height], [width, height]])
matrix = cv2.getPerspectiveTransform(pts1, pts2)
imgOutput = cv2.warpPerspective(img, matrix, (width,height))
cv2.imshow("imgOutput", imgOutput)
cv2.imshow("img", img)
for x in range(0, 4):
cv2.circle(img, (int(circles[x][0]), int(circles[x][1])), 3, (0, 0, 255), cv2.FILLED)
cv2.imshow("img", img)
cv2.setMouseCallback("img", mousePoints)
cv2.waitKey(1)
```

:::spoiler 一篇一個OpenCV函式(cvtColor)
cv2.cvtColor(src, code, dst=None, dstCn=None)
- 參數解釋:
src:輸入圖像即要進行顏色空間變換的原圖像,可以是Mat類。
code:轉換的代碼或標識,即在此確定將什麼制式的圖片轉換成什麼制式的圖片。
dst:它是與src圖像大小和深度相同的輸出圖像。它是一個可選參數。
dstCn:它是目標圖像中的頻道數。如果參數為0,則通道數自動從src和code決定。它是一個可選參數。
函數的作用是將一個圖像從一個顏色空間轉換到另一個顏色空間
但是從RGB向其他類型轉換時,必須明確指出圖像的顏色通道
前面我們也提到過,在opencv中,其默認的顏色制式排列是BGR而非RGB。
所以對於24位顏色圖像來說,
前8-bit是藍色,中間8-bit是綠色,最後8-bit是紅色。常見的R,G,B通道的取值範圍為:
. 0-255 :CV_8U類型圖片
. 0-65535: CV_16U類型圖片
. 0-1: CV_32F類型圖片
對於線性變換來說,這些取值範圍是無關緊要的。
但是對於非線性轉換,輸入的RGB圖像必須歸一化到其對應的取值範圍來或得最終正確的轉換結果,
例如從RGB->L*u*v轉換。
如果從一個8-bit類型圖像不經過任何縮放(scaling)直接轉換為32-bit浮點型圖像
函數將會以0-255的取值範圍來取代0-1的取值範圍
所以在使用cvtColor函數之前需要對圖像進行縮放如下:
```javascript=
img *=1./255
cvtColor(img, img, CV_BGR2Luv)
```
這裡列出的類型並不齊全,但是對於一般的圖像處理已經夠用。
需要特別說明的是RGB–>GRAY的轉換是我們常用的轉換格式,其轉換公式如下:
RGB[A] to Gray: Y=0.299*R+0.587*G+0.114B
上圖中出現的RGBA格式圖片,RGBA是代表Red(紅色)、Green(綠色)、Blue(藍色)和Alpha的色彩空間
雖然它有時候被描述為一個顏色空間,但是它其實是RGB模型附加了額外的資訊,可以屬於任何一種RGB顏色空間
Alpha引數一般用作不透明度引數,如果一個畫素的alpha通道數值為0%
那它就是完全透明的也就是肉眼不可見,而數值為100%則意味著一個完全不透明的畫素
傳統的數字影象就是alpha值為100%
需要注意的是cvtColor()函式不能直接將RGB影象轉換為二值影象(Binary Image)
需要藉助threshold()函式,其具體用法請查閱threshold().
```javascript=
# 使用opencv讀取影象,直接返回numpy.ndarray 物件,通道順序為BGR ,注意是BGR,通道值預設範圍0-255。
img = cv.imread(r".\1.png") # 相對路徑
cv.imshow("IMAGE_BGR",img) # 在Image視窗中顯示圖片img
img_gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY) # 將彩色影象轉換為灰度影象
img_hsv = cv.cvtColor(img, cv.COLOR_BGR2HSV) # 將彩色影象轉換為HSV影象
cv.imshow("IMAGE_GRAY",img_gray)
cv.imshow("IMAGE_HSV", img_hsv)
```
https://blog.csdn.net/keith_bb/article/details/53470170
:::
:::spoiler 一篇一個numpy函式()
```javascript=
//
```
https://hackmd.io/@yillkid/rJp5h90s8/https%3A%2F%2Fhackmd.io%2F%40yillkid%2FHy5a_5A-F#array
:::
###