1. 程式人生 > >opencv庫的基本使用(python)

opencv庫的基本使用(python)

1.圖片的讀取與儲存

# -*- coding: utf-8 -*-
# @Author: Xingmo

import cv2
import numpy as np

# 讀取圖片: cv2.imread(路徑,num) 其中num=0,為灰度影象;num=1為彩圖
img = cv2.imread('002.jpg',0)

# 建立視窗,cv2.namedWindow(視窗名)
cv2.namedWindow('image')

# 儲存圖片,cv2.imwrite(儲存圖片名,要儲存的圖片)
cv2.imwrite('002.jpg',img)
# 第三個引數針對特定的格式: 對於JPEG,其表示的是影象的質量,用0-100的整數表示(越高越清晰,壓縮級別越低),預設為95。  注意,cv2.IMWRITE_JPEG_QUALITY型別為Long,必須轉換成int。
cv2.imwrite('003.jpg',img,[int(cv2.IMWRITE_JPEG_QUALITY), 10])
# 對於PNG,第三個引數表示的是壓縮級別。cv2.IMWRITE_PNG_COMPRESSION,從0到9,壓縮級別越高,影象尺寸越小。預設級別為3
cv2.imwrite('004.png', img, [int(cv2.IMWRITE_PNG_COMPRESSION), 5])
# 圖片顯示,cv2.imshow(視窗名,要顯示的圖片)
cv2.imshow('image1',img)

# 複製img圖片
#emptyimage = img.copy()
# 建立空圖片
emptyimage = np.zeros(img.shape,np.uint8)
cv2.imshow('image2',emptyimage)

# 鍵盤繫結函式
cv2.waitKey(0)
# 釋放視窗
cv2.destroyAllWindows()
2.畫素點的操作,新增椒鹽噪聲
# -*- coding: utf-8 -*-
# @Author: Xingmo

import cv2
import numpy as np

# 新增椒鹽噪聲
def salt(img):
    for k in range(100):
        # 建立圖片隨機座標點
        i = int(np.random.random()*img.shape[0])
        j = int(np.random.random()*img.shape[1])
        # 圖片為灰度影象,有二維
        if img.ndim == 2:
            img[i,j] = 255
        # 圖片為彩色圖片,有三維,RGB
        elif img.ndim == 3:
            img[i,j,0] = 255
            img[i,j,1] = 255
            img[i,j,2] = 255
    return img

if __name__ == '__main__':
    # 讀取圖片
    img = cv2.imread('001.jpg')
    # 新增噪聲
    saltImage = salt(img)
    # 圖片顯示
    cv2.imshow("Salt", saltImage)
    # 圖片儲存
    cv2.imwrite('salt.jpg',saltImage)

    cv2.waitKey(0)
    cv2.destroyAllWindows()

3.彩色圖片各通道分離與合併
# -*- coding: utf-8 -*-
# @Author: Xingmo


import cv2

img = cv2.imread('001.jpg')

# split 返回BGR三個通道
b,g,r = cv2.split(img)

# merged 通道合併
merge = cv2.merge([b,g,r])
cv2.imshow('merge',merge)

#cv2.imshow("Red", r)
#cv2.imshow("Green", g)
#cv2.imshow("Blue", b)

cv2.waitKey(0)
cv2.destroyAllWindows()



4.直方圖的繪畫
# -*- coding: utf-8 -*-
# @Author: Xingmo

####### 說明 #######
# cv2.calcHist(images, channels, mask, histSize, ranges[, hist[, accumulate ]]) #返回hist
# 第一個引數為讀取的影象,必須用方括號括起來。
# 第二個引數是用於計算直方圖的通道,這裡使用灰度圖計算直方圖,所以就直接使用第一個通道;
# 第三個引數是Mask,這裡沒有使用,所以用None。
# 第四個引數是histSize,表示這個直方圖分成多少份(即多少個直方柱)。第二個例子將繪出直方圖,到時候會清楚一點。
# 第五個引數是表示直方圖中各個畫素的值,[0.0, 256.0]表示直方圖能表示畫素值從0.0到256的畫素。
# 最後是兩個可選引數,由於直方圖作為函式結果返回了,所以第六個hist就沒有意義了(待確定)
# 最後一個accumulate是一個布林值,用來表示直方圖是否疊加。
#######
# cv.PolyLine(img, polys, is_closed, color, thickness=1, lineType=8, shift=0)  # 返回None
# img        讀取的影象
# polys      多邊形曲線的陣列(各個座標點)
# is_closed  繪製的折線是否關閉的標誌,起始點是否有線連線,False為沒有
# color      折線的顏色 [b,g,r]
# thickness  折線邊緣的厚度
# lineType   線段的型別
# shift      頂點座標中的小數位數
########   說明END   #######


import cv2
import numpy as np


# 將直方圖(填充)轉化為圖片
def calcAndDrawHist(image, color):
    hist = cv2.calcHist([image], [0], None, [256], [0.0,255.0])
    # cv2.minMaxLoc 最大值maxVal和最小值minVal及它們的位置
    minVal, maxVal, minLoc, maxLoc = cv2.minMaxLoc(hist)
    # 建立全零影象
    histImg = np.zeros([256,256,3], np.uint8)
    hpt = int(0.95* 256);

    for h in range(256):
        # hpt=0.95*256 0.95防止最大值為整張圖片的高,每個hist與最大值的比*(256*0.95)即可表示該hist在圖片中的高度
        intensity = int(hist[h]*hpt/maxVal)
        # cv2.line(影象img,第一個點座標(x1,y1),第二個點座標(x2,y2),顏色[b,g,r])
        cv2.line(histImg,(h,256), (h,256-intensity), color)

    return histImg

# 將直方圖(折線)轉化為圖片
def DrawHist(img):
    # 建立空圖片
    h = np.zeros((256,256,3))
    # 直方圖中各bin的頂點位置
    bins = np.arange(256).reshape(256,1)
    # BGR三種顏色
    color = [ (255,0,0),(0,255,0),(0,0,255) ]

    for ch, col in enumerate(color):
        originHist = cv2.calcHist([img],[ch],None,[256],[0,256])
        # cv2.normalize(影象img,輸出影象,歸一化後最低值,歸一化後最大值,規範化型別 cv2.NORM_MINMAX:僅針對密集陣列)
        cv2.normalize(originHist, originHist,0,255*0.9,cv2.NORM_MINMAX)
        # np.around(array) 取整數,但資料型別仍為float
        hist=np.int32(np.around(originHist))
        # np.column_stack 將兩個1-D陣列作為列堆疊成2維陣列
        pts = np.column_stack((bins,hist))
        # cv2.polylines(影象img,多邊形曲線的陣列,繪製的折線是否關閉的標誌,折線顏色)
        cv2.polylines(h,[pts],False,col)
    # np.flipud 在上/下方向翻轉陣列。
    h=np.flipud(h)
    return h
'''
####### 灰度影象———直方圖(填充) #######
img = cv2.imread('001.jpg',0)

histimg = calcAndDrawHist(img,[255,255,255])
cv2.imshow('hist',histimg)

cv2.waitKey(0)
'''

####### 彩色影象———直方圖(填充) #######
if __name__ == '__main__':
    # 讀取圖片
    img = cv2.imread("001.jpg")
    # cv2.spilt 返回BGR三個通道
    b, g, r = cv2.split(img)

    # calcAndDrawHist(影象img,color填[b,g,r])
    histImgB = calcAndDrawHist(b, [255, 0, 0])
    histImgG = calcAndDrawHist(g, [0, 255, 0])
    histImgR = calcAndDrawHist(r, [0, 0, 255])

    cv2.imshow("histImgB", histImgB)
    cv2.imshow("histImgG", histImgG)
    cv2.imshow("histImgR", histImgR)
    cv2.imshow("Img", img)
####### 彩色影象———直方圖(折線) #######
if __name__ == '__main__':
    img = cv2.imread("001.jpg")
    h = DrawHist(img)
    cv2.imshow('colorhist',h)


cv2.waitKey(0)
cv2.destroyAllWindows()

結果顯示:

彩色影象———直方圖(填充)


彩色影象———直方圖(折線)


5.形態學運算:膨脹與腐蝕

# -*- coding: utf-8 -*-
# @Author: Xingmo

import cv2
import numpy as np

# 讀取影象
img = cv2.imread('004.jpg',0);
# 構造一個3×3的結構元素
element = cv2.getStructuringElement(cv2.MORPH_RECT,(3, 3))
# 膨脹影象 cv2.dilate(影象,元素結構)
dilate = cv2.dilate(img, element)
# 腐蝕影象 cv2.erode(影象,元素結構)
erode = cv2.erode(img, element)

# 將兩幅影象相減獲得邊,第一個引數是膨脹後的影象,第二個引數是腐蝕後的影象
result = cv2.absdiff(dilate,erode);

# 上面得到的結果是灰度圖,cv2.threshold將其二值化以便更清楚的觀察結果
# cv2.threshold(src , thresh, maxval, type[, dst])  返回retval、dst
# cv2.threshold(影象, 閾值  , 最大值, 閾值型別)     返回值型別、返回處理後圖像
# 閾值型別:THRESH_BINARY、THRESH_BINARY_INV、THRESH_TRUNC、THRESH_TOZERO、THRESH_TOZERO_INV
retval, result = cv2.threshold(result, 40, 255, cv2.THRESH_BINARY);

# 反色,即對二值圖每個畫素取反
result = cv2.bitwise_not(result);
# 顯示影象
cv2.imshow("origin",img);   # 原圖
cv2.imshow("result",result);# 邊緣檢測圖

cv2.waitKey(0)
cv2.destroyAllWindows()
結果顯示:


6.初級濾波器

# -*- coding: utf-8 -*-
# @Author: Xingmo

import cv2
import numpy as np

######## 線性過濾器 #######
# 低通濾波(平滑影象)
# cv2.blur(影象,濾波器大小(num,num))  #返回dst(處理後圖像)
#
# cv2.boxFilter(影象, -1, 濾波器大小(num,num)) #返回dst(處理後圖像)
# 第二個引數-1表示與原圖相同
#
# 高斯模糊
# cv2.GaussianBlur(影象,濾波器大小(num,num),X方向的高斯核心標準偏差) #返回dst(處理後圖像)
######## 線性過濾器END #######
#
######## 非線性過濾器 #######
# 中值濾波
# cv2.medianBlur(影象,濾波器大小num)
####### 非線性過濾器END #######

def salt(img):
    for k in range(100):
        # 建立圖片隨機座標點
        i = int(np.random.random()*img.shape[0])
        j = int(np.random.random()*img.shape[1])
        # 圖片為灰度影象,有二維
        if img.ndim == 2:
            img[i,j] = 255
        # 圖片為彩色圖片,有三維,RGB
        elif img.ndim == 3:
            img[i,j,0] = 255
            img[i,j,1] = 255
            img[i,j,2] = 255
    return img

if __name__ == '__main__':
    #
    img = cv2.imread('001.jpg',0)
    salt =salt(img)

    # 低通濾波
    dst1 = cv2.blur(salt,(5,5))
    # boxFilter
    dst2 = cv2.boxFilter(salt,-1,(5,5))
    # 高斯模糊
    dst3 = cv2.GaussianBlur(salt,(5,5),1.5)
    # 中值濾波
    dst4 = cv2.medianBlur(salt,5)

    # 影象顯示
    # 對於椒鹽噪聲而言,中值濾波效果是最好的,其他效果差不多
    cv2.imshow('salt',salt)
    cv2.imshow('blur',dst1)
    cv2.imshow('boxFilter',dst2)
    cv2.imshow('GaussianBlur',dst3)
    cv2.imshow('medianBlur',dst4)


cv2.waitKey(0)
cv2.destroyAllWindows()
結果顯示:



7.sobel

# -*- coding: utf-8 -*-
# @Author: Xingmo

####### cv2.sobel說明 #######
# cv2.Sobel(src, ddepth, dx, dy[, dst[, ksize[, scale[, delta[, borderType]]]]]) #返回dst(處理後圖像)
# scr      影象
# ddepth   輸出影象深度
#          S = 符號整型  U = 無符號整型  F = 浮點型
#          src.depth()= CV_8U,ddepth= -1 / CV_16S/ CV_32F/CV_64F
#          src.depth()= CV_16U/ CV_16S,ddepth= -1 CV_32F//CV_64F
#          src.depth()= CV_32F,ddepth= -1 CV_32F/CV_64F
#          src.depth()= CV_64F,ddepth= -1 /CV_64F
#          何時ddepth=-1,目的地影象將具有與源相同的深度
# dx
# dy
####### cv2.sobel說明END #######

import cv2
import numpy as np

img = cv2.imread('003.jpg', 0)

x = cv2.Sobel(img,cv2.CV_16S,1,0)
y = cv2.Sobel(img,cv2.CV_16S,0,1)

# cv2.convertScaleAbs 在輸入陣列的每個元素上,該函式依次執行三個操作:縮放,取絕對值,轉換為無符號8位型別
# 轉回uint8
absX = cv2.convertScaleAbs(x)
absY = cv2.convertScaleAbs(y)

# cv2.addWeighted(src1 , alpha, src2 , beta , gamma[, dst[, dtype]]) #返回dst(處理後圖像)
# cv2.addWeighted(輸入1, 分量1, 輸入2, 分量2, 標量)
# dst = src1*alpha + src2*beta + gamma
dst = cv2.addWeighted(absX,0.5,absY,0.5,0)

# 影象顯示
cv2.imshow('origin',img)
cv2.imshow("absX", absX)
cv2.imshow("absY", absY)
cv2.imshow("Result", dst)

cv2.waitKey(0)
cv2.destroyAllWindows()
結果顯示:

8.laplacian

# -*- coding: utf-8 -*-
# @Author: Xingmo

#######  cv2.Laplacian 說明 #######
# cv2.Laplacian(src, ddepth[, dst[, ksize[, scale[, delta[, borderType]]]]]) #返回dst(處理後圖像)
# src        影象
# ddepth     輸出影象深度
#            S = 符號整型  U = 無符號整型  F = 浮點型
#            src.depth()= CV_8U,ddepth= -1 / CV_16S/ CV_32F/CV_64F
#            src.depth()= CV_16U/ CV_16S,ddepth= -1 CV_32F//CV_64F
#            src.depth()= CV_32F,ddepth= -1 CV_32F/CV_64F
#            src.depth()= CV_64F,ddepth= -1 /CV_64F
#            何時ddepth=-1,目的地影象將具有與源相同的深度
# dst        輸出影象
# ksize      用於計算二階微分濾波器的孔徑大小,其大小必須是正數和奇數
# scale      縮放導數的比例常數,預設情況下沒有伸縮係數
# delta      在結果儲存之前新增到結果中的可選增量值,預設情況下沒有額外的值加到dst中
# borderType 判斷影象邊界的模式。這個引數預設值為cv2.BORDER_DEFAULT
#######  cv2.Laplacian 說明END #######

import cv2
import numpy as np

# 影象讀取
img = cv2.imread("004.jpg", 0)

gray_lap = cv2.Laplacian(img,cv2.CV_16S,ksize = 3)
# cv2.convertScaleAbs 在輸入陣列的每個元素上,該函式依次執行三個操作:縮放,取絕對值,轉換為無符號8位型別
# 轉回uint8
dst = cv2.convertScaleAbs(gray_lap)

# 影象顯示
cv2.imshow('origin',img)
cv2.imshow('laplacian',dst)

cv2.waitKey(0)
cv2.destroyAllWindows()
結果顯示:


由於laplacian對噪聲敏感,對圖片先去躁可得到更好的效果

blur = cv2.medianBlur(img,3)
blur = cv2.blur(img,(3,3))
此處有laplacain演算法原理

9.canny

# -*- coding: utf-8 -*-
# @Author: Xingmo

####### cv2.Canny 說明 #######
# cv2.Canny(image, threshold1, threshold2[, edges[, apertureSize[, L2gradient]]]) 返回edges(邊緣圖)
# image          原影象,該影象必須為單通道的灰度圖
# threshold1     第一個閾值
# threshold2     第二個閾值
# apertureSize   Sobel運算元的孔徑大小,其有預設值3
# L2gradient     是否使用L2範數,一個計算影象梯度幅值的標識,預設值false
####### cv2.Canny 說明END #######

import cv2
import numpy as np

# 讀取圖片
img = cv2.imread('004.jpg', 0)
# 高斯模糊
blur = cv2.GaussianBlur(img,(3,3),0)
canny = cv2.Canny(blur, 50, 200)

# 影象顯示
cv2.imshow('origin',img)
cv2.imshow('Canny', canny)

cv2.waitKey(0)
cv2.destroyAllWindows()
結果顯示: