智能資訊處理
一、 基礎影像識別(OpenCV)
OpenCV(開源計算機視覺庫)是一個開源的BSD許可庫,其中包含數百種計算機視覺演算法,本節課主要介紹OpenCV 2.x API,它本質上是一個C ++ API,與基于C的OpenCV 1.x API相反,
1. OpenCV特點
- 跨平臺:Windows、Linux、Android
- 開源免費,無論商業與否
- 高效快速,使用方便
2. OpenCV下載安裝
# 安裝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__)
3. 基礎學習
-
讀取圖片、視頻、呼叫外部攝像頭
# ========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'): breakwrite
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) -
基本操作:顏色空間轉換、模糊、邊緣檢測、膨脹、腐蝕
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) -
改變大小
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) -
視角變換
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) -
影像拼接
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)
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/228505.html
標籤:其他
