Python OpenCV _1基本操作(畫圖,迴圈播放影象,滑鼠事件,讀取中文路徑中的圖片)
阿新 • • 發佈:2018-11-23
此係列原始碼在我的GitHub裡:https://github.com/yeyujujishou19/Python-OpenCV
一,OpenCV的結構
A)根據功能和需求的不同,OpenCV中的函式介面大體可以分為如下部分:
core | 核心模組,主要包含了OpenCV中最基本的結構(矩陣,點線和形狀等),以及相關的基礎運算/操作。 |
imgproc | 影象處理模組,包含和影象相關的基礎功能(濾波,梯度,改變大小等),以及一些衍生的高階功能(影象分割,直方圖,形態分析和邊緣/直線提取等)。 |
highgui | 提供了使用者介面和檔案讀取的基本函式,比如影象顯示視窗的生成和控制,影象/視訊檔案的IO等。 |
B)如果不考慮視訊應用,以上三個就是最核心和常用的模組了。針對視訊和一些特別的視覺應用,OpenCV也提供了強勁的支援:
video: | 用於視訊分析的常用功能,比如光流法(Optical Flow)和目標跟蹤等。 |
calib3d: | 三維重建,立體視覺和相機標定等的相關功能。 |
features2d: | 二維特徵相關的功能,主要是一些不受專利保護的,商業友好的特徵點檢測和匹配等功能,比如ORB特徵。 |
object: | 目標檢測模組,包含級聯分類和Latent SVM |
ml: | 機器學習演算法模組,包含一些視覺中最常用的傳統機器學習演算法。 |
flann: | 最近鄰演算法庫,Fast Library for Approximate Nearest Neighbors,用於在多維空間進行聚類和檢索,經常和關鍵點匹配搭配使用。 |
gpu: | 包含了一些gpu加速的介面,底層的加速是CUDA實現。 |
photo: | 計算攝像學(Computational Photography)相關的介面,當然這只是個名字,其實只有影象修復和降噪而已。 |
stitching: | 影象拼接模組,有了它可以自己生成全景照片。 |
nonfree: | 受到專利保護的一些演算法,其實就是SIFT和SURF。 |
contrib: | 一些實驗性質的演算法,考慮在未來版本中加入的。 |
legacy: | 字面是遺產,意思就是廢棄的一些介面,保留是考慮到向下相容。 |
ocl: | 利用OpenCL並行加速的一些介面。 |
superres: | 超解析度模組,其實就是BTV-L1(Biliteral Total Variation – L1 regularization)演算法 |
viz: | 基礎的3D渲染模組,其實底層就是著名的3D工具包VTK(Visualization Toolkit)。 |
從使用的角度來看,和OpenCV2相比,OpenCV3的主要變化是更多的功能和更細化的模組劃分。
二,opencv基礎操作
A)基本繪圖
#匯入cv模組
import cv2 as cv
import numpy as np
# 可以在畫面上繪製線段,圓,矩形和多邊形等,還可以在影象上指定位置列印文字
import numpy as np
import cv2
# 定義一塊寬1600,高1200的畫布,初始化為白色
canvas = np.zeros((400, 600, 3), dtype=np.uint8) + 255 #(400, 600, 3) 寬,高,通道
# 畫一條縱向的正中央的黑色分界線
cv2.line(canvas, (300, 0), (300, 399), (0, 0, 0), 2) #(300, 0) 寬,高
# 畫一條右半部份畫面以199為界的橫向分界線
cv2.line(canvas, (300, 199), (599, 199), (0, 0, 0), 2) #(300, 0) 寬,高
# 左半部分的右下角畫個紅色的圓
cv2.circle(canvas, (150, 300), 88, (0, 0, 255), 5) #(80, 300), 100-》圓心,半徑
# 左半部分的左下角畫個藍色的矩形
cv2.rectangle(canvas, (10, 300), (50, 390), (255, 0, 0), thickness=3) #(10, 10), (60, 60) 左上角座標, 右下角座標,
# 定義兩個三角形,並執行內部綠色填充
triangles = np.array([
[(150, 240), (95, 333), (205, 333)],
[(60, 160), (20, 217), (100, 217)]])
cv2.fillPoly(canvas, triangles, (0, 255, 0))
# 畫一個黃色五角星
# 第一步通過旋轉角度的辦法求出五個頂點
phi = 4 * np.pi / 5
rotations = [[[np.cos(i * phi), -np.sin(i * phi)], [i * np.sin(phi), np.cos(i * phi)]] for i in range(1, 5)]
pentagram = np.array([[[[0, -1]] + [np.dot(m, (0, -1)) for m in rotations]]], dtype=np.float)
# 定義縮放倍數和平移向量把五角星畫在左半部分畫面的上方
pentagram = np.round(pentagram * 80 + np.array([160, 120])).astype(np.int)
# 將5個頂點作為多邊形頂點連線,得到五角星
cv2.polylines(canvas, pentagram, True, (0, 255, 255), 9)
# 按畫素為間隔從左至右在畫面右半部份的上方畫出HSV空間的色調連續變化
for x in range(302, 600):
color_pixel = np.array([[[round(180*float(x-302)/298), 255, 255]]], dtype=np.uint8)
line_color = [int(c) for c in cv2.cvtColor(color_pixel, cv2.COLOR_HSV2BGR)[0][0]]
cv2.line(canvas, (x, 0), (x, 197), line_color)
# 如果定義圓的線寬大於半徑,則等效於畫圓點,隨機在畫面右下角的框內生成座標
np.random.seed(42)
n_pts = 30
pts_x = np.random.randint(310, 590, n_pts) #x範圍
pts_y = np.random.randint(210, 390, n_pts) #y範圍
pts = zip(pts_x, pts_y)
# 畫出每個點,顏色隨機
for pt in pts:
pt_color = [int(c) for c in np.random.randint(0, 255, 3)]
cv2.circle(canvas, pt, 3, pt_color, 5)
# 在左半部分最上方列印文字,按此方法不能顯示中文
# cv2.putText(canvas,
# '列印的文字just english',
# (5, 15),
# cv2.FONT_HERSHEY_SIMPLEX,
# 0.5,
# (0, 0, 0),
# 1)
# cv2.imshow('視窗名稱', canvas)
# cv2.waitKey()
# OpenCV-Python在圖片上輸出中文
# 在Python中,可以藉助PIL(Python Imaging Library)模組實現
from PIL import Image, ImageDraw, ImageFont
# 影象從OpenCV格式轉換成PIL格式
pil_img = cv2.cvtColor(canvas,cv2.COLOR_BGR2RGB)#cv2和PIL中顏色的hex碼的儲存順序不同,需轉RGB模式
pilimg = Image.fromarray(pil_img)#Image.fromarray()將陣列型別轉成圖片格式,與np.array()相反
draw = ImageDraw.Draw(pilimg)#PIL圖片上列印漢字
#引數1:字型檔案路徑,引數2:字型大小;Windows系統“simhei.ttf”預設儲存在路徑:C:\Windows\Fonts中
font = ImageFont.truetype("SIMLI.TTF",30,encoding="utf-8")
draw.text((0,0),"列印的文字 English",(255,0,0),font=font)
cv2img = cv2.cvtColor(np.array(pilimg),cv2.COLOR_RGB2BGR)#將圖片轉成cv2.imshow()可以顯示的陣列格式
cv2.imshow("hanzi 漢字",cv2img) #顯示視窗仍然不能顯示漢字
cv2.waitKey()
cv2.destroyAllWindows()
程式碼結果:
B)迴圈播放圖片
#匯入cv模組
import time
import cv2
import os
import sys
from itertools import cycle
# =====================OpenCV視窗顯示===============================
# img = cv2.imread('D:/test/1.jpg')
# cv2.imshow('視窗標題', img)
# cv2.waitKey()
# =====================OpenCV視窗迴圈===============================
frame_path="D:/test" # 圖片的資料夾路徑
# 列出frames資料夾下的所有圖片
filenames = os.listdir(frame_path)
# 通過itertools.cycle生成一個無限迴圈的迭代器,每次迭代都輸出下一張影象物件
img_iter = cycle([cv2.imread(os.sep.join([frame_path, x])) for x in filenames])
key = 0
while key & 0xFF != 27:
cv2.imshow('window title', next(img_iter))
key = cv2.waitKey(1000) #1000為間隔1000毫秒 cv2.waitKey()引數不為零的時候則可以和迴圈結合產生動態畫面
程式碼結果:
動態顯示圖片,無法截圖了
C)滑鼠事件
#匯入cv模組
import time
import cv2
import os
import sys
from itertools import cycle
# 定義滑鼠事件回撥函式
def on_mouse(event, x, y, flags, param):
# 滑鼠左鍵按下,擡起,雙擊
if event == cv2.EVENT_LBUTTONDOWN:
print('左鍵按下 ({}, {})'.format(x, y))
elif event == cv2.EVENT_LBUTTONUP:
print('左鍵彈起 ({}, {})'.format(x, y))
elif event == cv2.EVENT_LBUTTONDBLCLK:
print('左鍵雙擊 ({}, {})'.format(x, y))
# 滑鼠右鍵按下,擡起,雙擊
elif event == cv2.EVENT_RBUTTONDOWN:
print('右鍵按下 ({}, {})'.format(x, y))
elif event == cv2.EVENT_RBUTTONUP:
print('右鍵彈起 ({}, {})'.format(x, y))
elif event == cv2.EVENT_RBUTTONDBLCLK:
print('右鍵雙擊 ({}, {})'.format(x, y))
# 滑鼠中/滾輪鍵(如果有的話)按下,擡起,雙擊
elif event == cv2.EVENT_MBUTTONDOWN:
print('中間鍵按下 ({}, {})'.format(x, y))
elif event == cv2.EVENT_MBUTTONUP:
print('中間鍵彈起 ({}, {})'.format(x, y))
elif event == cv2.EVENT_MBUTTONDBLCLK:
print('中間鍵雙擊 ({}, {})'.format(x, y))
# 滑鼠移動
elif event == cv2.EVENT_MOUSEMOVE:
print('移動到 ({}, {})'.format(x, y))
# 為指定的視窗繫結自定義的回撥函式
cv2.namedWindow('window title')
img = cv2.imread('D:/2.jpg')
cv2.imshow('window title', img)
cv2.setMouseCallback('window title', on_mouse) # 第一個引數為要繫結的視窗名稱,第二個引數為要繫結的滑鼠事件
cv2.waitKey()
程式碼結果:
D)從帶中文的路徑中讀取圖片,並將圖片儲存到帶中文的路徑中
#!/usr/bin/env python
# coding: utf-8
import numpy as np
import cv2
#可以讀取帶中文路徑的圖
def cv_imread(file_path,type=0):
cv_img=cv2.imdecode(np.fromfile(file_path,dtype=np.uint8),-1)
if(type==0):
if(len(cv_img.shape)==3):
cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2GRAY)
return cv_img
readPath="D:/測試/2.jpg"
image=cv_imread(readPath,type=1)
#將圖片儲存到帶中文的路徑裡
savePath="D:/測試/3.jpg"
cv2.imencode('.jpg', image)[1].tofile(savePath)
程式碼結果:
歡迎掃碼關注我的微信公眾號