1. 程式人生 > >Python OpenCV _1基本操作(畫圖,迴圈播放影象,滑鼠事件,讀取中文路徑中的圖片)

Python OpenCV _1基本操作(畫圖,迴圈播放影象,滑鼠事件,讀取中文路徑中的圖片)

此係列原始碼在我的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)

程式碼結果:

 

歡迎掃碼關注我的微信公眾號