Opencv及常用方法示例程式碼

boss-dog發表於2020-10-22

包括一些Opencv的基本示例程式碼,方便以後查閱。

1.1在Pycharm中執行tensorflow出現的問題

解決python呼叫TensorFlow時出現FutureWarning: Passing (type, 1) or ‘1type’ as a synonym of type is deprecate
https://blog.csdn.net/bigdream123/article/details/99467316
python Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2 FMA
https://blog.csdn.net/wukai0909/article/details/97306316

#注意tensorflow的輸出格式和平常不同
import tensorflow as tf
hello = tf.constant("hello tf!")
sess = tf.Session()
print(sess.run(hello))

1.2案例1:圖片的讀取和展示

import cv2
srcImage = cv2.imread("E:\\pictures\\12.jpg",1)
cv2.imshow("srcImage",srcImage)
cv2.waitKey(0)
# PS:在Python中圖片的名稱、輸出視窗等都不能有中文,這點和C++不同

1.3案例2:圖片寫入

import cv2
srcImage = cv2.imread("E:\\pictures\\12.jpg",1)
cv2.imwrite("srcImage.jpg",srcImage)#第一個引數是影像名,第二個引數是圖片的資料

1.4案例3:不同圖片質量儲存

①JPG的壓縮:有失真壓縮

import cv2
srcImage = cv2.imread("E:\\pictures\\12.jpg",1)
cv2.imwrite("srcImage.jpg",srcImage,[cv2.IMWRITE_JPEG_QUALITY,0])
#數字0表示壓縮的比例,範圍是0-100,0是最高的壓縮比,影像效果最差

②PNG的壓縮:無失真壓縮且具有透明度屬性

import cv2
srcImage = cv2.imread("E:\\pictures\\12.jpg",1)
cv2.imwrite("srcImage.png",srcImage,[cv2.IMWRITE_PNG_COMPRESSION,0])
#數字0表示壓縮的比例,範圍是0-9,0是最低的壓縮比,影像效果最好

1.5畫素操作基礎

①對於RGB影像
eg.一個影像1.14M = 7205473*8 bit/8 (B)
含義:寬×高×三個畫素通道×每個顏色變數是八位的 / 8(轉化為位元組要除8)
②對於PNG影像
除了RGB三個通道,還要加上透明度alpha 通道

1.6案例4:畫素讀取寫入

import cv2
srcImage = cv2.imread("E:\\pictures\\12.jpg",1)
#畫素的讀取
(b,g,r) = srcImage[400,400]
#Opencv中的畫素排布是BGR的格式 [400,400]表示該座標的畫素值
print("b="+str(b)+",g="+str(g)+",r="+str(r))

#畫素的寫入,畫出一條第10行第100至第110行第110列的直線
#10 100 ----- 110 100
for i in range(1,100):
    srcImage[10+i,100] = (255,0,0)
cv2.imshow("srcImage",srcImage)
cv2.waitKey(0)

1.8tensorflow常量變數定義

import tensorflow as tf
data1 = tf.constant(2.5) #定義常量
data2 = tf.constant(2,dtype=tf.int32)
data3 = tf.Variable(10,name='var') #定義變數
print(data1)
print(data3)  #直接輸出的是資料的資訊
#列印常量
sess = tf.Session()
print(sess.run(data1))
print(sess.run(data2))
#列印變數
init = tf.global_variables_initializer()
sess.run(init)
print(sess.run(data3))

# 輸出:
# Tensor("Const:0", shape=(), dtype=float32)
# <tf.Variable 'var:0' shape=() dtype=int32_ref>
# 2.5
# 2
# 10

1.9tensorflow運算原理

1.tensorflow的本質是 = tensor + graphs
(tensor是張量、資料的意思,op即option操作運算,graphs是計算圖、資料操作的意思,)
2.Session是計算的核心,可以理解為一個運算的互動環境
3.在上一節中,我們Session之後沒有進行其他的操作,正常情況下是要close的:sess.close()
若不想這麼麻煩,可以這樣操作:

import tensorflow as tf
data1 = tf.Variable(10,name='var')
init = tf.global_variables_initializer()
sess = tf.Session()
with sess:
    sess.run(init)
    print(sess.run(data1))

1.10常量變數四則運算

①常量的四則運算

import tensorflow as tf
data1 = tf.constant(6)
data2 = tf.constant(2)
dataAdd = tf.add(data1,data2) #加
dataMul = tf.multiply(data1,data2) #乘
dataSub = tf.subtract(data1,data2) #減
dataDiv = tf.divide(data1,data2) #除
with tf.Session() as sess:
    print(sess.run(dataAdd))
    print(sess.run(dataMul))
    print(sess.run(dataSub))
    print(sess.run(dataDiv))
print('end!')

# 輸出:
# 8
# 12
# 4
# 3.0
# end!

②常量與變數的四則運算
eval()方法:用於直接輸出,相當於獲取了一個預設的session,然後執行run的操作

import tensorflow as tf
data1 = tf.constant(6)
data2 = tf.Variable(2)
dataAdd = tf.add(data1,data2) #加
dataCopy = tf.assign(data2,dataAdd) # dataAdd賦值給data2
init = tf.global_variables_initializer()
with tf.Session() as sess:
    sess.run(init)
    print('sess.run(dateCopy)',sess.run(dataCopy)) #將8賦給data2
    print('dataCopy.eval()',dataCopy.eval()) #data2+dataAdd:8+6=14
    print('tf.get_default_session',tf.get_default_session().run(dataCopy))#14+6=20
print('end!')

1.11矩陣基礎1

①tf.placeholder(dtype, shape=None, name=None)
TensorFlow中的佔位符,用於傳入外部資料。
引數:dtype:資料型別;shape:資料的維度,預設為None,表示沒有限制;name:名稱
示例:

import tensorflow as tf
data1 = tf.placeholder(tf.float32)
data2 = tf.placeholder(tf.float32)
dataAdd = tf.add(data1,data2)
with tf.Session() as sess:
    print(sess.run(dataAdd,feed_dict={data1:6,data2:2}))
#1.張量dataAdd 2.語法:data(feed_dict={引數1:6,引數2:2})

②tensorflow中的矩陣運算
矩陣的定義:[[ 6,6 ]]表示一行兩列的資料,外層的[ ]表示行,裡層的[ ]表示列

import tensorflow as tf
data1 = tf.constant([[6,6]])
data2 = tf.constant([[2],[2]])
data3 = tf.constant([[3,3]])
data4 = tf.constant([[1,2],[3,4],[5,6]])
print(data4.shape) #列印該矩陣的維度 3行兩列
with tf.Session() as sess:
    print(sess.run(data4)) #列印整個矩陣
    print(sess.run(data4[0])) #列印矩陣第一行 
    print(sess.run(data4[:,0])) #列印矩陣第一列
    print(sess.run(data4[0,1])) #列印矩陣第一行第二列的元素

# 輸出:
# 輸出:
# (3, 2)
# [[1 2]
#  [3 4]
#  [5 6]]
# [1 2]
# [1 3 5]

1.12矩陣基礎2

注意矩陣乘法matmul()和multiply()兩種方法的不同

import tensorflow as tf
data1 = tf.constant([[6,6]])
data2 = tf.constant([[2],[2]])
data3 = tf.constant([[3,3]])
data4 = tf.constant([[1,2],[3,4],[5,6]])
matMul = tf.matmul(data1,data2)
matMul2 = tf.multiply(data1,data2)
matAdd = tf.add(data1,data3)
with tf.Session() as sess:
    print(sess.run(matMul)) #矩陣相乘1*2 * 2*1 = 1*1
    print(sess.run(matMul2))  # 矩陣相乘1*2 * 2*1 = 2*2
    print(sess.run(matAdd)) #矩陣相加
    #通過中括號的方式可以一次列印多個值
    print(sess.run([matMul,matAdd]))

# 輸出:
# [[24]]
#[[12 12]
# [12 12]]
# [[9 9]]
# [array([[24]]), array([[9, 9]])]

1.13矩陣基礎3

①特殊矩陣的初始化

import tensorflow as tf
mat1 = tf.zeros([2,3]) #設2*3的矩陣元素全為0
mat2 = tf.ones([3,2]) #設3*2的矩陣元素全為1
mat3 = tf.fill([2,3],15) #填充2*3的矩陣元素全為15
with tf.Session() as sess:
    print(sess.run(mat1))
    print(sess.run(mat2))
    print(sess.run(mat3))

②linspace方法將區間取等分,zeros_like表示矩陣取相同的維度

mat1 = tf.constant([[2],[3],[4]])
mat2 = tf.zeros_like(mat1) #表示mat2矩陣和mat1矩陣的維度一樣
mat3 = tf.linspace(0.0,2.0,11) #矩陣的元素在0-2之間等分
mat4 = tf.random_uniform([2,3],-1,2) #表示定義一個2*3的矩陣,元素在-1到2區間隨機取

1.14numpy模組使用

import numpy as np
data1 = np.array([1,2,3,4,5])
print(data1)
data2 = np.array(([1,2],[3,4]))
print(data2)
print(data1.shape,data2.shape) #列印矩陣的維度
print(np.zeros([2,3]),np.ones([2,2])) #zeros和ones
data2[1,0] = 5 #將data2矩陣中第二行第一列的元素賦值為5
print(data2)
#矩陣的基本運算
data3 = np.ones([2,3])
print(data3*2) #對應元素相乘
print(data3/3) #對應元素相除
print(data3+2) #對應元素相加
#矩陣+ *
data4 = np.array([[1,2,3],[4,5,6]])
print(data3+data4)
print(data3*data4)

1.15matplotlib模組的使用

import numpy as np
import matplotlib.pyplot as plt
x = np.array([1,2,3,4,5,6,7,8])
y = np.array([3,5,7,6,2,6,10,15])
plt.plot(x,y,'red') #繪製折線,引數:x軸,y軸,顏色
plt.plot(x,y,'g',lw=10) #'g'表示綠色,lw是折現的寬度
#三種影像:折線,餅狀,柱狀
x = np.array([1,2,3,4,5,6,7,8])
y = np.array([3,5,7,6,2,6,10,15])
plt.bar(x,y,0.5,alpha=1,color='b')
#0.5表示柱狀的寬度,alpha表示透明度,color表示顏色
plt.show()

輸出:
在這裡插入圖片描述

2.1圖片縮放1

resize()函式,第一個引數為源圖,第二個引數為要縮放的寬和高,插值的型別。

import cv2
img = cv2.imread("E:\\pictures\\4.jpg",1)
imgInfo = img.shape
print(imgInfo)
height = imgInfo[0]
width = imgInfo[1]
mode = imgInfo[2] #存放方式,即通道數
dstHeight = int(height*0.5)
dstWidth = int(width*0.5)
dst = cv2.resize(img,(dstWidth,dstHeight))
cv2.imshow("dst",dst)
print(dst.shape)
cv2.waitKey(0)

# 輸出:
# (434, 650, 3)
# (217, 325, 3)

輸出格式:高度(行)、寬度(列)、通道數

2.2圖片縮放2

https://blog.csdn.net/csdnforyou/article/details/82315683
①最近鄰域插值法
說明:假設原圖src:1020 效果圖dst:510,則效果圖由原圖縮放而來,dst上的一點(1,2)對應於src上的(2,4),設dst上的畫素點x2,y2,src上的畫素點x1,y1,計算公式為:
x1 = x2 (src 行 / 目標行)即:x1 = x2(10/5)= 12 = 2
y1 = y2 (src 列 / 目標列)即:y1 = y2(20/10)= 2
2 = 4
若計算得一畫素點為12.3,則自動取12
②雙線性插值法
在這裡插入圖片描述
上圖中原圖中只有(15,22),(15,23),(16,22),(16,23)四個點,目標影像中新增了(15.2,22.3)這個點,雙線性差值法則是根據這個新的點的周圍四個點來確定這個點的值,
A1=20%上 + 80%下;B1 = 30%左 + 70%
最終點的確定:A1
30%+A2
70% B1
20% + B2
80%

2.3圖片縮放3

前面已經掌握了演算法的原理和圖片縮放得API:resize函式,這裡看下演算法得原始碼

import cv2
import numpy as np
img = cv2.imread("E:\\pictures\\4.jpg",1)
imgInfo = img.shape
height = imgInfo[0]
width = imgInfo[1]
dstHeight = int(height/2)
dstWidth = int(width/2)
dst = np.zeros((dstHeight,dstWidth,3),np.uint8) #初始化,以便下面畫素賦值
for i in range(0,dstHeight): #行
    for j in range(0,dstHeight): #列
        iNew = int(i*(height*1.0/dstHeight))
        jNew = int(j*(width*1.0)/dstWidth)
        dst[i,j] = img[iNew,jNew]
cv2.imshow("dst",dst)
print(dst.shape)
cv2.waitKey(0)

# 輸出:
# (217, 325, 3)

2.4圖片剪下

在這裡插入圖片描述
舉例:剪下影像x軸100-200,y軸100-300

import cv2
img = cv2.imread("E:\\pictures\\4.jpg",1)
imgInfo = img.shape
dst = img[100:200,100:300]
cv2.imshow("dst",dst)
print(dst.shape)
cv2.waitKey(0)

# 輸出:(100, 200, 3)

2.5圖片位移

①示例程式

import cv2
import numpy as np
img = cv2.imread("E:\\pictures\\4.jpg",1)
imgInfo = img.shape
height = imgInfo[0]
width = imgInfo[1]
matShift = np.float32([[1,0,100],[0,1,200]]) #2*3的偏移矩陣
dst = cv2.warpAffine(img,matShift,(height,width))
cv2.imshow("dst",dst)
cv2.waitKey(0)

②API介紹:warpAffine()
就拿上面的程式為例:[[1,0,100],[0,1,200]]是23的矩陣,拆分成22和21的兩個矩陣,假設A是22的矩陣,即[[1,0], [0,1]],B是21的矩陣,即[[100],[200]],C是x和y。根據公式:AC+B = [[1x+0y],[0x+1y]]+[[100],[200]] = [[x+100],[y+200]]
③用演算法原理程式設計:將原圖往右移動100個畫素
PS:先將dst初始化為黑色,因為是將影像右移100個畫素,所以行不變,列改變,即先將dst的列先加100,再將原圖dst的(列-100)再賦值給dst

import cv2
import numpy as np
img = cv2.imread("E:\\pictures\\4.jpg",1)
imgInfo = img.shape
height = imgInfo[0]
width = imgInfo[1]
dst = np.zeros((height,width,3),np.uint8) #初始化,以便下面畫素賦值
for i in range(0,height): #行
    for j in range(0,width-100): #列
        dst[i,j+100] = img[i,j]
cv2.imshow("dst",dst)
cv2.waitKey(0)

2.6圖片映象

①步驟:①建立一個足夠大的“畫板”②將一副影像分別從前向後、從後向前繪製③繪製中心分割線
②程式

import cv2
import numpy as np
img = cv2.imread("E:\\pictures\\4.jpg",1)
imgInfo = img.shape
height = imgInfo[0]
width = imgInfo[1]
deep = imgInfo[2] #影像的通道數
newImgInfo = (height*2,width,deep) #建立一個畫板
dst = np.zeros(newImgInfo,np.uint8) #初始化,以便下面畫素賦值
for i in range(0,height): #行
    for j in range(0,width): #列
        dst[i,j] = img[i,j] #先繪製上半部分
        #因為是上下映象,所以x不變,y*2
        #下半部分影像座標,x不變,y=2*h-y-1
        dst[height*2-i-1,j] = img[i,j]
for i in range(0,width):
    dst[height,i] = (0,0,255) #繪製中心分割線
cv2.imshow("dst",dst)
cv2.waitKey(0)

2.7圖片縮放

參考圖片位移

import cv2
import numpy as np
img = cv2.imread("E:\\pictures\\4.jpg",1)
imgInfo = img.shape
height = imgInfo[0]
width = imgInfo[1]
matScale = np.float32([[0.5,0,0],[0,0.5,0]])
dst = cv2.warpAffine(img,matScale,(int(width/2),int(height/2)))
cv2.imshow("dst",dst)
cv2.waitKey(0)

2.8圖片仿射變換

import cv2
import numpy as np
img = cv2.imread("E:\\pictures\\4.jpg",1)
imgInfo = img.shape
height = imgInfo[0]
width = imgInfo[1]
#已知原圖上的三個點(左上角,左下角,右上角)
matSrc = np.float32([[0,0],[0,height-1],[width-1,0]])
#將這三個點對映到目標影像上
matDst = np.float32([[50,50],[300,height-200],[width-300,100]])
#組合兩個矩陣
matAffine = cv2.getAffineTransform(matSrc,matDst)
dst = cv2.warpAffine(img,matAffine,(width,height))
cv2.imshow('dst',dst)
cv2.waitKey(0)

輸出:
在這裡插入圖片描述

2.9圖片旋轉

①API:getRotationMatrix2D()介紹:第一個引數:旋轉的中心;第二個引數:旋轉的角度;第三個引數:縮放的係數
②程式

import cv2
import numpy as np
img = cv2.imread("E:\\pictures\\4.jpg",1)
imgInfo = img.shape
height = imgInfo[0]
width = imgInfo[1]
#定義旋轉矩陣
matRotate = cv2.getRotationMatrix2D((height*0.5,width*0.5),45,0.5)
dst = cv2.warpAffine(img,matRotate,(height,width))
cv2.imshow('dst',dst)
cv2.waitKey(0)

3.1影像灰度處理1

# 方法一:一開始圖片匯入的時候就以灰度影像顯示
img0 = cv2.imread('image0.jpg',0)
# 方法二:使用cvtColor,將彩色圖轉為灰度圖
dst = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) #顏色空間轉換

3.2影像灰度處理2

方法三:所謂灰度圖,即RBG三通道的值一樣,R=G=B = gray

import cv2
import numpy as np
img = cv2.imread("E:\\pictures\\4.jpg",1)
imgInfo = img.shape
height = imgInfo[0]
width = imgInfo[1]
# RGB  R=G=B = gray  (R+G+G)/3
dst = np.zeros((height,width,3),np.uint8)
for i in range(0,height): #行
    for j in range(0,width): #列
        (b,g,r) = img[i,j] #表示原圖每個畫素的三通道的值
        gray = (int(b) + int(g) +int(r))/3
        dst[i,j] = np.uint8(gray)
cv2.imshow('dst',dst)
cv2.waitKey(0)

方法四:公式:gray = r0.299 + g0.587 +b*0.114
前面的程式與上面相同,就for迴圈這裡改變

for i in range(0,height): #行
    for j in range(0,width): #列
        (b,g,r) = img[i,j] #表示原圖每個畫素的三通道的值
        b = int(b)
        g = int(g)
        r = int(r)
        gray = r*0.299+g*0.587+b*0.114
        dst[i,j] = np.uint8(gray)

對於方法四中的公式法,浮點數轉為整型的過程中,會存在丟失精度的可能,可以將原值進行放大的操作,如乘1000等等

3.3顏色反轉

①灰度影像的顏色反轉 0-255 255-當前

import cv2
import numpy as np
img = cv2.imread("E:\\pictures\\4.jpg",1)
imgInfo = img.shape
height = imgInfo[0]
width = imgInfo[1]
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
dst = np.zeros((height,width,1),np.uint8) #轉為灰度影像後是一個通道
for i in range(0,height): #行
    for j in range(0,width): #列
        grayPixel = gray[i,j]
        dst[i,j] = 255-grayPixel
cv2.imshow('dst',dst)
cv2.waitKey(0)

②彩色影像的顏色反轉 RGB 255-R=newR:0-255 255-當前

import cv2
import numpy as np
img = cv2.imread("E:\\pictures\\4.jpg",1)
imgInfo = img.shape
height = imgInfo[0]
width = imgInfo[1]
dst = np.zeros((height,width,3),np.uint8) #彩色影像有3個通道
for i in range(0,height): #行
    for j in range(0,width): #列
        (b,g,r) = img[i,j]
        dst[i,j] = (255-b,255-g,255-r) #對三個通道進行賦值
cv2.imshow('dst',dst)
cv2.waitKey(0)

3.4馬賽克

原理:馬賽克是有形狀的,有圓形、矩形等等,本節講的是矩形。工作原理:首先選取馬賽克的範圍,然後再選取一個小區域,將這區域中的所有畫素值,選用其中某一個點的畫素值來表示。

import cv2
import numpy as np
img = cv2.imread("E:\\pictures\\4.jpg",1)
imgInfo = img.shape
height = imgInfo[0]
width = imgInfo[1]
for m in range(100,300): #行
    for n in range(100,200): #列
        # 將10*10畫素的所有值用一個畫素點表示
        if m%10 == 0 and n%10 == 0:
            for i in range(0,10):
                for j in range(0,10):
                    (b,g,r) = img[m,n]
                    img[i+m,j+n] = (b,g,r)
cv2.imshow('dst',img)
cv2.waitKey(0)

輸出:
在這裡插入圖片描述

3.5毛玻璃

理解:毛玻璃操作與馬賽克的區別:馬賽克是選取一個區域,其中該區域的畫素值是由某指定的點的畫素值,而毛玻璃中該區域的畫素值是該區域中隨機一個點的畫素值。

import cv2
import numpy as np
import random
img = cv2.imread("E:\\pictures\\4.jpg",1)
imgInfo = img.shape
height = imgInfo[0]
width = imgInfo[1]
dst = np.zeros((height,width,3),np.uint8)
mm = 8
for m in range(0,height-mm): #行-mm,防止溢位
    for n in range(0,width-mm): #列-mm
        index = int(random.random()*8) #產生隨機數0-7
        (b,g,r) = img[m+index,n+index]
        dst[m,n] = (b,g,r)
cv2.imshow('dst',dst)
cv2.waitKey(0)

輸出:
在這裡插入圖片描述
PS:可以發現效果圖中,圖片的右邊與下邊有黑邊,這是因為在for迴圈中,為了防止溢位,height和width都減去了mm即8個畫素的值,一開始dst是設定的黑色。

3.6圖片融合

方法:將圖片1乘以一個權重 + 圖片2乘以一個權重,每個畫素值都這樣,要保證兩圖片大小一致。

import cv2
import numpy as np
img0 = cv2.imread("E:\\pictures\\34.jpg",1)
img1 = cv2.imread("E:\\pictures\\35.jpg",1)
imgInfo = img0.shape
height = imgInfo[0]
width = imgInfo[1]
#定義要融合的部分ROI,這裡只融合圖片的四分之一
roiH = int(height/2)
roiW = int(width/2)
img0ROI = img0[0:roiH,0:roiW]
img1ROI = img1[0:roiH,0:roiW]
#dst
dst = np.zeros((roiH,roiW,3),np.uint8)
dst = cv2.addWeighted(img0ROI,0.5,img1ROI,0.5,0) #0.5表示權重
cv2.imshow('dst',dst)
cv2.waitKey(0)

3.7邊緣檢測1

邊緣檢測的實質是卷積運算
canny運算元的步驟:1.轉化為灰度影像 2.採用高斯濾波 3.呼叫canny方法

import cv2
img = cv2.imread("E:\\pictures\\4.jpg",1)
imgInfo = img.shape
height = imgInfo[0]
width = imgInfo[1]
cv2.imshow('src',img)
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
imgG = cv2.GaussianBlur(gray,(3,3),0) #(3,3)表示核心的大小
dst = cv2.Canny(img,50,50) #如果圖片經過卷積後大於50這個值,就認為是邊緣
cv2.imshow('dst',dst)
cv2.waitKey(0)

輸出:
在這裡插入圖片描述
在這裡插入圖片描述

3.8邊緣檢測2

Sobel運算元:步驟
①運算元模板:分為豎直方向的運算元和水平方向的運算元
Eg.[ 1 2 1 [ 1 0 -1
0 0 0 2 0 -2
-1 -2 -1] 為豎直方向的運算元 1 0 -1] 為水平方向的運算元
②圖片卷積
舉個公式:[ 1 2 3 4 ] [ a b c d ] a1+b2+c3+d4 = dst
③閾值判斷
Sqrt( aa + bb) 若大於閾值,則為邊緣,小於則不是。
a指的是豎直方向的運算元和豎直方向的圖片進行卷積後得到的就是a,叫梯度,同理b是水平方向的梯度

# 用原始碼編寫的情況
import cv2
import numpy as np
import math
img = cv2.imread("E:\\pictures\\4.jpg",1)
imgInfo = img.shape
height = imgInfo[0]
width = imgInfo[1]
cv2.imshow('src',img)
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
dst = np.zeros((height,width,1),np.uint8)
for i in range(0,height-2):
    for j in range(0,width-2):
    #這裡減2的原因是:運算元模板是3*3的,右下角畫素的座標為2,2,防止溢位
    #下面的計算就是用的上面舉例的運算元模板
        gy = gray[i,j]*1+gray[i,j+1]*2+gray[i,j+2]*1-\
             gray[i+2,j]*1-gray[i+2,j+1]*2-gray[i+2,j+2]*1
        #採用豎直方向的運算元,橫著計算
        gx = gray[i,j]*1+gray[i+1,j]*2+gray[i+2,j]*1-\
             gray[i,j+2]*1-gray[i+1,j+2]*2-gray[i+2,j+2]*1
        #採用水平方向的運算元,豎著計算
        grad = math.sqrt(gx*gx+gy*gy)
        if grad >50:
            dst[i,j] = 255 #是邊界,設為白色
        else:
            dst[i,j] = 0 #不是邊界,設為黑色,和背景相同
cv2.imshow('dst',dst)
cv2.waitKey(0)

輸出:
在這裡插入圖片描述

3.9浮雕效果

浮雕和邊緣檢測比較類似,也是計算梯度的過程
公式為:newP = gray0 - gray1 + 150
(兩個灰度值相減,凸出對比,加150增強浮雕的效果)

import cv2
import numpy as np
img = cv2.imread("E:\\pictures\\4.jpg",1)
imgInfo = img.shape
height = imgInfo[0]
width = imgInfo[1]
cv2.imshow('src',img)
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
# newP = gray0 - gray1 + 150
dst = np.zeros((height,width,1),np.uint8)
for i in range(0,height):
    for j in range(0,width-1):
        grayP0 = int(gray[i,j]) #獲取當前畫素的灰度值
        grayP1 = int(gray[i,j+1]) #獲取下一個畫素的灰度值
        newP = grayP0-grayP1 + 150
        if newP > 255:
            newP = 255
        if newP < 0:
            newP = 0
        dst[i,j] = newP
cv2.imshow('dst',dst)
cv2.waitKey(0)

輸出:
在這裡插入圖片描述

3.10顏色對映

原理:將原影像的RGB畫素值,對映到你自己認為的一個顏色區間

import cv2
import numpy as np
img = cv2.imread("E:\\pictures\\4.jpg",1)
imgInfo = img.shape
height = imgInfo[0]
width = imgInfo[1]
cv2.imshow('src',img)
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
# RGB 產生藍色的效果 b=b*1.5 g=g*1.3
dst = np.zeros((height,width,3),np.uint8)
for i in range(0,height):
    for j in range(0,width):
        (b,g,r) = img[i,j]
        b = b*1.5
        g = g*1.3
        if b > 255:
            b = 255
        if g > 255:
            g = 255
        dst[i,j] = (b,g,r)
cv2.imshow('dst',dst)
cv2.waitKey(0)

輸出:
在這裡插入圖片描述

3.11油畫特效

步驟:1.彩色影像到灰度影像的轉換
2.分成若干個區域,比如77或者88區域,統計每個區域中的灰度值
3.將0-255劃分為幾個等級,並把第二步中的灰度值對映到這個等級中
4.統計之前劃分割槽域對映到第三步等級中的個數
5.用統計出來的平均值替換原影像的畫素值

import cv2
import numpy as np
img = cv2.imread("E:\\pictures\\4.jpg",1)
imgInfo = img.shape
height = imgInfo[0]
width = imgInfo[1]
cv2.imshow('src',img)
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
dst = np.zeros((height,width,3),np.uint8)
for i in range(4,height-4):
    for j in range(4,width-4):
        array1 = np.zeros(8,np.uint8) #定義8個灰度等級
        for m in range(-4,4): #選取8*8的區域
            for n in range(-4,4):
                #步驟三:灰度等級的統計
                p1 = int(gray[i+m,j+n]/32) #p1範圍是0-7
                array1[p1] = array1[p1] + 1 #表示當前的畫素值,完成累加
        currentMax = array1[0] #獲取array1中哪個段內的畫素值最多
        l = 0
        for k in range(0,8):
            if currentMax < array1[k]:
                currentMax = array1[k]
                l = k
        #統計均值
        for m in range(-4,4):
            for n in range(-4,4):
                if gray[i+m,j+n] >=(l*32) and gray[i+m,j+n]<=((l+1)*32):
                    (b,g,r) = img[i+m,j+n]
        dst[i,j] = (b,g,r)
cv2.imshow('dst',dst)
cv2.waitKey(0)

在這裡插入圖片描述

3.12線段繪製

cv2.line(dst,(100,100),(300,300),(0,0,255),20,cv2.LINE_AA)

引數說明:1.線段繪製的目標影像 2.線段繪製的起始點 3.線段繪製的結束點 4.線段的顏色 5.線段的寬度 6.線段的型別LINE_AA為抗鋸齒形。

3.13矩形圓形任意多邊形繪製

①繪製矩形

cv2.rectangle(dst,(50,100),(200,300),(0,0,255),-1)

引數說明:1.矩形繪製的目標影像 2.矩形的左上角座標 3.矩形的右下角座標 4.矩形線條的顏色 5.是否填充,若為-1,表示填充;若為大於0的數,表示線段的寬度
②繪製圓形

cv2.circle(dst,(50,50),50,(0,0,255),2)

引數說明:1.圓形繪製的目標影像 2.圓心的座標 3.圓的半徑 4圓形線條的顏色 5.是否填充,若為-1,表示填充;若為大於0的數,表示線段的寬度
③繪製橢圓

cv2.ellipse(dst,(100,100),(150,100),0,0,180,(0,0,255),-1)

引數說明:1.橢圓繪製的目標影像 2.橢圓的中心點座標 3.橢圓的長軸和短軸的長度 4.橢圓的角度 5.起始角度 6.結束角度 7.橢圓的顏色 8.是否填充
④繪製任意多邊形

points = [] #表示多邊形的各個頂點座標
cv2.polylines(dst,[points],True,(0,0,255))

3.14文字圖片繪製

import cv2
img = cv2.imread("E:\\pictures\\image0.jpg",1)
font = cv2.FONT_HERSHEY_SIMPLEX #字型的選擇
cv2.rectangle(img,(200,100),(500,400),(0,255,0),3)
cv2.putText(img,'this is a flower',(100,300),font,1,(200,100,255),2,cv2.LINE_AA)
#引數:1.dst 2.文字內容 3.座標 4.字型 5.字型大小 6.字型顏色 7.字型粗細 8.線條線型
cv2.imshow('dst',img)
cv2.waitKey(0)

輸出:
在這裡插入圖片描述

import cv2
img = cv2.imread("E:\\pictures\\image0.jpg",1)
height = int(img.shape[0]*0.2)
width = int(img.shape[1]*0.2)
imgResize = cv2.resize(img,(width,height)) #將要加上的圖片縮放處理
for i in range(0,height):
    for j in range(0,width):
        img[i+200,j+350] = imgResize[i,j]
cv2.imshow('dst',img)
cv2.waitKey(0)

輸出:
在這裡插入圖片描述

4.1彩色圖片直方圖

API:calcHist() 繪製影像的直方圖

import cv2
import numpy as np
def ImageHist(image,type): #定義個繪製直方圖的函式
    color = (255,255,255) #設定顏色
    windowName = 'Gray'
    if type == 31:
        color = (255,0,0)
        windowName = 'Blue Hist'
    elif type == 32:
        color = (0,255,0)
        windowName = 'Green Hist'
    elif type == 33:
        color = (0,0,255)
        windowName = 'Red Hist'
    hist = cv2.calcHist([image],[0],None,[256],[0.0,255.0])
    #直方圖函式引數說明:1.圖片 2.當前通道 3.掩膜 4.直方圖的大小,分成多少類
    #                  5.表明直方圖中各個畫素的值0-255表明畫素從0-255都遍歷一次
    #開始繪圖
    #首先要知道直方圖中最大值最小值以及它們的座標,為了下面的座標歸一化
    minValue,maxValue,minIndex,maxIndex = cv2.minMaxLoc(hist)
    histImage = np.zeros([256,256,3],np.uint8)
    for h in range(256):
        intenNormal = int(hist[h]*256/maxValue) #將值歸一化,使繪圖美觀
        cv2.line(histImage,(h,256),(h,256-intenNormal),color)
    cv2.imshow(windowName,histImage)
    return histImage

img = cv2.imread('E:\\pictures\\image0.jpg')
channels = cv2.split(img) #將RGB影像分割成R G B 三個通道
for i in range(0,3):
    ImageHist(channels[i],31+i)
cv2.waitKey(0)

輸出:
在這裡插入圖片描述

4.2直方圖均衡化

API:equalizeHist 直方圖的均衡化
merge 影像通道的合成
split 影像通道的分解
①灰度影像的直方圖均衡化

import cv2
img = cv2.imread('E:\\pictures\\image0.jpg',1)
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
cv2.imshow('src',gray)
dst = cv2.equalizeHist(gray)
cv2.imshow('dst',dst)
cv2.waitKey(0)

輸出:
在這裡插入圖片描述
②彩色影像的直方圖均衡化

import cv2
img = cv2.imread('E:\\pictures\\image0.jpg',1)
(b,g,r) = cv2.split(img) #通道分解
bH = cv2.equalizeHist(b)
gH = cv2.equalizeHist(g)
rH = cv2.equalizeHist(r)
result = cv2.merge((bH,gH,rH)) #通道合成
cv2.imshow('src',img)
cv2.imshow('dst',result)
cv2.waitKey(0)

輸出:
在這裡插入圖片描述
③YUV影像的直方圖均衡化

import cv2
img = cv2.imread('E:\\pictures\\image0.jpg',1)
imgYUV = cv2.cvtColor(img,cv2.COLOR_BGR2YCrCb)
channelYUV = cv2.split(imgYUV)
channelYUV[0] = cv2.equalizeHist(channelYUV[0])
channels = cv2.merge(channelYUV)
result = cv2.cvtColor(channels,cv2.COLOR_BGR2YCrCb)
cv2.imshow('src',imgYUV)
cv2.imshow('dst',result)
cv2.waitKey(0)

輸出:
在這裡插入圖片描述

4.3圖片修補

API:inpaint 圖片修補
步驟:1.需要一個損壞的圖 2.知道損壞的畫素座標 3.呼叫API

4.4灰度直方圖原始碼

# 本質:統計每個畫素灰度 出現的概率 0-255
import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread('E:\\pictures\\image0.jpg',1)
imgInfo = img.shape
height = imgInfo[0]
width = imgInfo[1]
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
count = np.zeros(256,np.float) #表示每個畫素值在每個灰度等級下出現的概率,256個等級
for i in range(0,height):
    for j in range(0,width):
        pixel = gray[i,j] #獲取每個灰度等級的畫素
        index = int(pixel) #轉為int型別
        count[index] = count[index]+1
for i in range(0,255): #每個灰度等級出現的概率
    #分子是count,分母是所有的畫素
    count[i] = count[i]/(height*width)
x = np.linspace(0,255,256)
y = count
plt.bar(x,y,0.9,alpha=1,color='b')
plt.show()
cv2.waitKey(0)

輸出:
在這裡插入圖片描述

4.5彩色直方圖原始碼

import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread('E:\\pictures\\image0.jpg',1)
imgInfo = img.shape
height = imgInfo[0]
width = imgInfo[1]
count_b = np.zeros(256,np.float)
count_g = np.zeros(256,np.float)
count_r = np.zeros(256,np.float)
for i in range(0,height):
    for j in range(0,width):
        (b,g,r) = img[i,j]
        index_b = int(b)
        index_g = int(g)
        index_r = int(r)
        count_b[index_b] = count_b[index_b]+1
        count_g[index_g] = count_g[index_g]+1
        count_r[index_r] = count_r[index_r]+1
for i in range(0,256):
    count_b[i] = count_b[i]/(height*width)
    count_g[i] = count_g[i]/(height*width)
    count_r[i] = count_r[i]/(height*width)
x = np.linspace(0,255,256)
y1 = count_b
plt.figure()
plt.bar(x,y1,0.9,alpha=1,color='b')
y2 = count_g
plt.figure()
plt.bar(x,y2,0.9,alpha=1,color='g')
y3 = count_r
plt.figure()
plt.bar(x,y3,0.9,alpha=1,color='r')
plt.show()
cv2.waitKey(0)

在這裡插入圖片描述

3.15灰度直方圖均衡化原始碼分析

①累計概率的概念:假設直方圖灰度等級1出現的概率是0.2,2出現的概率是0.3,3出現的概率是0.1,則1的累計概率是0.2,2的累計概率是0.2+0.3=0.5,3的累計概率是0.2+0.3+0.1=0.6。
假設256個灰度等級中,100的累計概率為0.5,則255*0.5=new的值作為對映的新的值

import cv2
import numpy as np
img = cv2.imread('E:\\pictures\\image0.jpg',1)
imgInfo = img.shape
height = imgInfo[0]
width = imgInfo[1]
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
cv2.imshow('src',gray)
count = np.zeros(256,np.float) #表示每個畫素值在每個灰度等級下出現的概率,256個等級
for i in range(0,height):
    for j in range(0,width):
        pixel = gray[i,j] #獲取每個灰度等級的畫素
        index = int(pixel) #轉為int型別
        count[index] = count[index]+1
for i in range(0,255): #每個灰度等級出現的概率
    #分子是count,分母是所有的畫素
    count[i] = count[i]/(height*width)
#計算累計概率
sum1 = float(0)
for i in range(0,256):
    sum1 = sum1 + count[i]
    count[i] = sum1
#計算對映表
map1 = np.zeros(256,np.uint16)
for i in range(0,256):
    map1[i] = np.uint16(count[i]*255)
#對映
for i in range(0,height):
    for j in range(0,width):
        pixel = gray[i,j]
        gray[i,j] = map1[pixel]
cv2.imshow('dst',gray)
cv2.waitKey(0)

輸出:
在這裡插入圖片描述

3.16彩色影像直方圖均衡化原始碼分析

PS:和上節的程式碼差不多,灰度圖是一個通道,彩色圖是三個通道

import cv2
import numpy as np
img = cv2.imread('E:\\pictures\\image0.jpg',1)
imgInfo = img.shape
height = imgInfo[0]
width = imgInfo[1]
cv2.imshow('src',img)
count_b = np.zeros(256,np.float)
count_g = np.zeros(256,np.float)
count_r = np.zeros(256,np.float)
for i in range(0,height):
    for j in range(0,width):
        (b,g,r) = img[i,j]
        index_b = int(b)
        index_g = int(g)
        index_r = int(r)
        count_b[index_b] = count_b[index_b]+1
        count_g[index_g] = count_g[index_g] + 1
        count_r[index_r] = count_r[index_r] + 1
for i in range(0,255):
    #分子是count,分母是所有的畫素
    count_b[i] = count_b[i]/(height*width)
    count_g[i] = count_g[i] / (height * width)
    count_r[i] = count_r[i] / (height * width)
#計算累計概率
sum_b = float(0)
sum_g = float(0)
sum_r = float(0)
for i in range(0,256):
    sum_b = sum_b + count_b[i]
    sum_g = sum_g + count_g[i]
    sum_r = sum_r + count_r[i]
    count_b[i] = sum_b
    count_g[i] = sum_g
    count_r[i] = sum_r
#計算對映表
map_b = np.zeros(256,np.uint16)
map_g = np.zeros(256,np.uint16)
map_r = np.zeros(256,np.uint16)
for i in range(0,256):
    map_b[i] = np.uint16(count_b[i]*255)
    map_g[i] = np.uint16(count_b[i] * 255)
    map_r[i] = np.uint16(count_b[i] * 255)
#對映
dst = np.zeros((height,width,3),np.uint8)
for i in range(0,height):
    for j in range(0,width):
        (b,g,r) = img[i,j]
        b = map_b[b]
        g = map_b[g]
        r = map_b[r]
        dst[i,j] = (b,g,r)
cv2.imshow('dst',dst)
cv2.waitKey(0)

輸出:
在這裡插入圖片描述

3.17亮度增強

原理:將每個畫素點三通道的畫素值增加,即p = p + 40

import cv2
import numpy as np
img = cv2.imread('E:\\pictures\\image0.jpg',1)
imgInfo = img.shape
height = imgInfo[0]
width = imgInfo[1]
cv2.imshow('src',img)
dst = np.zeros((height,width,3),np.uint8)
for i in range(0,height):
    for j in range(0,width):
        (b,g,r) = img[i,j]
        bb = int(b)+40
        gg = int(g)+40
        rr = int(r)+40
        if bb>255:
            bb = 255
        if gg>255:
            gg = 255
        if rr>255:
            rr = 255
        dst[i,j] = (bb,gg,rr)
cv2.imshow('dst',dst)
cv2.waitKey(0)

輸出:
在這裡插入圖片描述

3.18磨皮美白

API:bilateralFilter 雙邊濾波

import cv2
img = cv2.imread('E:\\pictures\\image1.png',1)
dst = cv2.bilateralFilter(img,15,35,35)
cv2.imshow('src',img)
cv2.imshow('dst',dst)
cv2.waitKey(0)

輸出:
在這裡插入圖片描述

3.19高斯均值濾波

API:GaussianBlur 高斯均值濾波

#呼叫API
import cv2
img = cv2.imread('E:\\pictures\\image0.JPG',1)
cv2.imshow('src',img)
dst = cv2.GaussianBlur(img,(5,5),1.5)
cv2.imshow('dst',dst)
cv2.waitKey(0)
# 原始碼分析
import cv2
import numpy as np
img = cv2.imread('E:\\pictures\\image0.JPG', 1)
imgInfo = img.shape
height = imgInfo[0]
width = imgInfo[1]
dst = np.zeros((height,width,3),np.uint8)
for i in range(3,height-3):
    for j in range(3,width-3):
        sum_b = int(0)
        sum_g = int(0)
        sum_r = int(0)
        for m in range(-3,3):#-3 -2 -1 0 1 2
            for n in range(-3,3):
                (b,g,r) = img[i+m,j+n]
                sum_b = sum_b+int(b)
                sum_g = sum_g+int(g)
                sum_r = sum_r+int(r)
        b = np.uint8(sum_b/36)
        g = np.uint8(sum_g/36)
        r = np.uint8(sum_r/36)
        dst[i,j] = (b,g,r)
cv2.imshow('dst',dst)
cv2.waitKey(0)

3.20中值濾波

#原始碼分析
import cv2
import numpy as np
img = cv2.imread('image11.jpg',1)
imgInfo = img.shape
height = imgInfo[0]
width = imgInfo[1]
img = cv2.cvtColor(img,cv2.COLOR_RGB2GRAY)
cv2.imshow('src',img)
dst = np.zeros((height,width,3),np.uint8)
collect = np.zeros(9,np.uint8)
for i in range(1,height-1):
    for j in range(1,width-1):
        k = 0
        for m in range(-1,2):
            for n in range(-1,2):
                gray = img[i+m,j+n]
                collect[k] = gray
                k = k+1
        # 0 1 2 3 4 5 6 7 8
        #   1 
        for k in range(0,9):
            p1 = collect[k]
            for t in range(k+1,9):
                if p1<collect[t]:
                    mid = collect[t]
                    collect[t] = p1
                    p1 = mid
        dst[i,j] = collect[4]
cv2.imshow('dst',dst)
cv2.waitKey(0)

相關文章