OpenCV(開源計算機視覺庫)是一個開源的BSD許可庫,其中包含數百種計算機視覺算法。本節課主要介紹OpenCV 2.x API,它本質上是一個C ++ API,與基於C的OpenCV 1.x API相反。python
# 安裝numpy庫 pip install numpy -i https://pypi.tuna.tsinghua.edu.cn/simple # 安裝opencv庫 pip install opencv-python -i https://pypi.tuna.tsinghua.edu.cn/simple #下載完成後輸入如下Python代碼檢查 import cv2 print(cv2.__version__)
讀取圖片、視頻、調用外部攝像頭linux
# ========read============ img = cv2.imread("./lena.png") # 讀取照片 # DISPLAY cv2.imshow("Lena", img) # 展現照片 cv2.waitKey(0) # 阻擋顯示 # =====read video import cv2 frameWidth = 640 # 顯示長 frameHeight = 480 # 顯示寬 cap = cv2.VideoCapture("./test_video.mp4") # VideoCapture()中參數是0,表示打開筆記本的內置攝像頭, # 參數是視頻文件路徑則打開視頻,如vc = cv2.VideoCapture("../testi.mp4") while True: success, img = cap.read() # vc.read()按幀讀取視頻,success,img是獲cap.read()方法的兩個返回值。其中success是布爾值, # 若是讀取幀是正確的則返回True,若是文件讀取到結尾,它的返回值就爲False。img就是每一幀的圖像,是個三維矩陣。 img = cv2.resize(img, (frameWidth, frameHeight)) # 從新設置大小 cv2.imshow("Result", img) # 若沒有按下q鍵,則每1毫秒顯示一幀 if cv2.waitKey(1) & 0xFF == ord('q'): break # ===========read webcam================== import cv2 # 假如攝像流爲 cap, 那麼設置參數是cap.set(參數編號,參數) frameWidth = 640 frameHeight = 480 cap = cv2.VideoCapture(0) # 讀取攝像頭 cap.set(3, frameWidth) cap.set(4, frameHeight) cap.set(10, 150) while True: success, img = cap.read() cv2.imshow("Result", img) if cv2.waitKey(1) & 0xFF == ord('q'): break
writeweb
import cv2 img = cv2.imread("opencv-logo.png") # 用OpenCV讀取opencv-logo.png圖片並保存到變量img中 cv2.namedWindow("Image", cv2.WINDOW_NORMAL) # 給顯示圖片的窗口命名,而且採用默認模式 cv2.imshow("Image", img) # 展現圖片 cv2.waitKey(0) # 等待用戶按鍵退出 cv2.imwrite("output.jpg", img) # 將圖片內容寫入到output.jpg中
像素和數組分析算法
import cv2 img = cv2.imread("opencv-logo.png", 1) # 第2個參數是1表示使用圖像的默認顏色和色彩通道,若是是0則表示以黑白形式讀入該圖片 print(img) # 會發現是一個數組 print(type(img)) # 類型是<class 'numpy.ndarray'> print(len(img)) # 表示數組的行 print(len(img[0])) # 表示數組的列 print(len(img[0][0])) # 表示通道數,這裏是3,表示RGB紅綠藍3通道 print(img.shape) # 直接打印出這3項參數 print(img.dtype) # uint8,數據類型是8bit的無符號整數,也就是色彩從0~255 print(img[10, 5]) # 第10行第5列的像素,是一個有3個數的一維數組 print(img[:, :, 0]) # 打印出第一個通道的全部數據,即R通道在每一個點上的數據 print(img.size) # 像素的個數
import numpy as np import cv2 # zeros(shape, dtype=float, order=‘C’) # shape:形狀 shape = [a , b, m] a*b*通道數 # dtype:數據類型,可選參數,默認numpy.float64 # 全黑色圖片 black = np.zeros([150, 200, 1], 'uint8') # 全部通道都是0,顯示黑色 cv2.imshow("Black", black) print(black[0, 0, :]) # ones()返回一個全1的n維數組,一樣也有三個參數:shape(用來指定返回數組的大小)、dtype(數組元素的類型)、 # order(是否之內存中的C或Fortran連續(行或列)順序存儲多維數據)。後兩個參數都是可選的,通常只需設定第一個參數。和zeros同樣 # 幾乎黑色圖片 ones = np.ones([150, 200, 3], 'uint8') cv2.imshow("Ones", ones) print(ones[0, 0, :]) # 全白色圖片 white = np.ones([150, 200, 3], 'uint16') white *= (2 ** 16 - 1) # 點乘,全部通道都是最高,顯示白色 cv2.imshow("White", white) print(white[0, 0, :]) # 全藍色圖片 color = ones.copy() # 深拷貝 color[:, :] = (255, 0, 0) # 藍色通道最高,其他通道爲0,顯示藍色 cv2.imshow("Blue", color) print(color[0, 0, :]) cv2.waitKey(0)
基本操做:顏色空間轉換、模糊、邊緣檢測、膨脹、腐蝕shell
import cv2 import numpy as np # 彩色圖像轉換爲灰度圖像(以灰度圖或者單通道圖讀入) # 對圖像進行高斯模糊(去噪) # 計算圖像梯度,根據梯度計算圖像邊緣幅值與角度 # 沿梯度方向進行非極大值抑制(邊緣細化) # 雙閾值邊緣鏈接處理 # 二值化圖像輸出結果 img = cv2.imread("./lena.png") kernel = np.ones((5, 5), np.uint8) imgGray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # cv2.cvtColor(p1,p2) 是顏色空間轉換函數,p1是須要轉換的圖片,p2是轉換成何種格式。 # cv2.COLOR_BGR2RGB 將BGR格式轉換成RGB格式 # cv2.COLOR_BGR2GRAY 將BGR格式轉換成灰度圖片 # (7, 7)表示高斯矩陣的長與寬都是7,標準差取0 imgBlur = cv2.GaussianBlur(imgGray, (7, 7), 0) # 高斯模糊濾波是一種線性平滑濾波,適用於消除高斯噪聲,普遍應用於圖像處理的減噪過程 # 行canny邊緣檢測 # 很明顯,Canny邊緣檢測的效果是很顯著的。相比普通的梯度算法大大抑制了噪聲引發的僞邊緣, # 並且是邊緣細化,易於後續處理。對於對比度較低的圖像,經過調節參數,Canny算法也能有很好的效果。 # 參數說明: src表示輸入的圖片, # thresh1表示最小閾值,thresh2表示最大閾值,用於進一步刪選邊緣信息 imgCanny = cv2.Canny(img, 150, 200) # 腐蝕與膨脹屬於形態學操做,所謂的形態學,就是改變物體的形狀,形象理解一些:腐蝕=變瘦 膨脹=變胖 imgDialation = cv2.dilate(imgCanny, kernel, iterations=1) # 膨脹操做原理:存在一個kernel, # 在圖像上進行從左到右,從上到下的平移, # 若是方框中存在白色,那麼這個方框內全部的顏色都是白色 imgEroded = cv2.erode(imgDialation, kernel, iterations=1) # 在原圖的每個小區域裏取最小值,因爲是二值化圖像,只要有一個點爲0,則都爲0, # 來達到瘦身的目的。所以在下面的例子中,咱們就可使用腐蝕來將圖片中的一些毛刺或者說很細小的東西給去掉。 cv2.imshow("Gray Image", imgGray) cv2.imshow("Blur Image", imgBlur) cv2.imshow("Canny Image", imgCanny) cv2.imshow("Dialation Image", imgDialation) cv2.imshow("Eroded Image", imgEroded) cv2.waitKey(0)
改變大小windows
import cv2 import numpy as np img = cv2.imread("./shapes.png") print(img.shape) imgResize = cv2.resize(img, (1000, 500)) # 改變大小 print(imgResize.shape) imgCropped = img[46:119, 352:495] # 裁剪座標爲[y0:y1, x0:x1 print(imgCropped.shape) cv2.imshow("Image", img) cv2.imshow("Image Resize", imgResize) cv2.imshow("Image Cropped", imgCropped) cv2.waitKey(0)
增長圖形和文字數組
import cv2 import numpy as np img = np.zeros((512, 512, 3), np.uint8) print(img) img[:] = 255, 0, 0 # 藍色通道最大 # 線 cv2.line(img, (0, 0), (img.shape[1], img.shape[0]), (0, 255, 0), 3) # 方形 cv2.rectangle(img, (0, 0), (250, 350), (0, 0, 255), 2) # 圓形 cv2.circle(img, (400, 50), 30, (255, 255, 0), 5) # 文字 cv2.putText(img, " OPENCV ", (300, 200), cv2.FONT_HERSHEY_COMPLEX, 1, (0, 150, 0), 3) cv2.imshow("Image", img) cv2.waitKey(0)
視角變換app
import cv2 import numpy as np img = cv2.imread("./cards.jpg") width, height = 250, 350 # 數位的區別,一個在內存中佔分別32和64個bits,也就是4bytes或8bytes # 數位越高浮點數的精度越高 pts1 = np.float32([[111, 219], [287, 188], [154, 482], [352, 440]]) pts2 = np.float32([[0, 0], [width, 0], [0, height], [width, height]]) # 透視變換(Perspective Transformation)是將成像投影到一個新的視平面(Viewing Plane), # 也稱做投影映射(Projective Mapping)。如圖1,經過透視變換ABC變換到A'B'C'。 # 將四個點組成的平面轉換成另四個點組成的一個平面 matrix = cv2.getPerspectiveTransform(pts1, pts2) # 經過warpPerspective函數來進行變換 imgOutput = cv2.warpPerspective(img, matrix, (width, height)) cv2.imshow("Image", img) cv2.imshow("Output", imgOutput) cv2.waitKey(0)
圖像拼接ide
import cv2 import numpy as np def stack_images(scale, img_array): rows = len(img_array) cols = len(img_array[0]) rows_available = isinstance(img_array[0], list) width = img_array[0][0].shape[1] height = img_array[0][0].shape[0] if rows_available: for x in range(0, rows): for y in range(0, cols): if img_array[x][y].shape[:2] == img_array[0][0].shape[:2]: img_array[x][y] = cv2.resize(img_array[x][y], (0, 0), None, scale, scale) else: img_array[x][y] = cv2.resize(img_array[x][y], (img_array[0][0].shape[1], img_array[0][0].shape[0]), None, scale, scale) if len(img_array[x][y].shape) == 2: img_array[x][y] = cv2.cvtColor(img_array[x][y], cv2.COLOR_GRAY2BGR) image_blank = np.zeros((height, width, 3), np.uint8) hor = [image_blank] * rows hor_con = [image_blank] * rows for x in range(0, rows): hor[x] = np.hstack(img_array[x]) ver = np.vstack(hor) else: for x in range(0, rows): if img_array[x].shape[:2] == img_array[0].shape[:2]: img_array[x] = cv2.resize(img_array[x], (0, 0), None, scale, scale) else: img_array[x] = cv2.resize(img_array[x], (img_array[0].shape[1], img_array[0].shape[0]), None, scale, scale) if len(img_array[x].shape) == 2: img_array[x] = cv2.cvtColor(img_array[x], cv2.COLOR_GRAY2BGR) hor = np.hstack(img_array) ver = hor return ver img = cv2.imread('./lena.png') imgGray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) imgStack = stack_images(0.5, ([img, imgGray, img], [img, img, img])) # np.vstack():在豎直方向上堆疊 # # np.hstack():在水平方向上平鋪 imgHor = np.hstack((img, img)) imgVer = np.vstack((img, img)) cv2.imshow("Horizontal", imgHor) cv2.imshow("Vertical", imgVer) cv2.imshow("ImageStack", imgStack) cv2.waitKey(0)