计算机视觉 OpenCV 的基础操作

导入工具包

import cv2  # pip install opencv_python 但导入的是cv2库
import numpy as np  # 基于数组对象的科学计算库
import matplotlib.pyplot as plt   # 画图数据库

一、图像基本操作

1.1 读入图片

img = cv2.imread('Lena.png',cv2.IMREAD_GRAYSCALE)  # Lena.png 为图片的路径 如:C:/Users/Lena.png;cv2.IMREAD_GRAYSCALE为灰白图
# img = cv2.imread('Lena.png',cv2.IMREAD_COLOR)  # cv2.IMREAD_COLOR为彩色图
cv2.imshow("img",img)  # cv2.imshow() 传入'名称'与 图片数据,展示图片
cv2.waitKey(0)  # 图片展示时间/ms,0为按任意键盘取消展示
cv2.destroyAllWindows() # 结束所有进程

1. 2 保存图片

cv2.imwrite('Lena_gray.png',img)  # 保存图片;'Lena_gray.png'为保存路径,或 C:/Users/Lena_gray.png

1.3 图片部分截取 

# 图片部分截取
Lena_part = img[150:400,150:400]  # 定义截取部分的 X,Y,原图的左上角为(0,0)
cv2.imwrite('Lena_part.png',Lena_part ) # 保存图片

1.4 图片通道提取 

b,g,r = cv2.split(cv2.imread('Lena.png',cv2.IMREAD_COLOR)) # 提取彩色图片的b,g,r通道
Lena_b_g_r = np.hstack((b,g,r))  # hstack图像沿横向拼接;vstack图像沿纵向拼接
# Lena_b_g_r = np.vstack((b,g,r))
cv2.imwrite('Lena_b_g_r.png',Lena_b_g_r) # 保存图像

1.5 图片通道合并

img=cv2.merge((b,g,r))

1.6 图像边界填充 

top_size,bottom_size,left_size,right_size = (50,50,50,50)  # 上下左右填充大小

replicate = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size, borderType=cv2.BORDER_REPLICATE)
reflect = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size,cv2.BORDER_REFLECT)
reflect101 = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size, cv2.BORDER_REFLECT_101)
wrap = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size, cv2.BORDER_WRAP)
constant = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size,cv2.BORDER_CONSTANT, value=0)

plt.subplot(231), plt.imshow(img, 'gray'), plt.title('ORIGINAL')
plt.subplot(232), plt.imshow(replicate, 'gray'), plt.title('REPLICATE')
plt.subplot(233), plt.imshow(reflect, 'gray'), plt.title('REFLECT')
plt.subplot(234), plt.imshow(reflect101, 'gray'), plt.title('REFLECT_101')
plt.subplot(235), plt.imshow(wrap, 'gray'), plt.title('WRAP')
plt.subplot(236), plt.imshow(constant, 'gray'), plt.title('CONSTANT')

# plt.xticks([])  # 关闭X轴刻度
# plt.yticks([])  # 关闭Y轴刻度
plt.show()

对图片进行边界填充,主要是改变图片最外围的边框,共有五种方法:
BORDER_REPLICATE:复制法,也就是复制最边缘像素。
BORDER_REFLECT:反射法,对感兴趣的图像中的像素在两边进行复制例如:
BORDER_REFLECT_101:反射法,也就是以最边缘像素为轴,对称
BORDER_WRAP:外包装法
BORDER_CONSTANT:常量法,常数值填充。 

1.7 图像融合 

'''==========================图片融合=========================='''
img_cat=cv2.imread('cat.png')
img_dog=cv2.imread('dog.png')
img_cat = cv2.resize(img_cat, (640, 640))  #将两个图片改为同样大小
img_dog = cv2.resize(img_dog, (640, 640))
res = cv2.addWeighted(img_cat, 0.5, img_dog, 0.5, 0) #猫占0.5权重,狗占0.5权重, 0为偏置项像素整体加0
res = np.hstack((img_cat,img_dog,res)) # 图片拼接
cv2.imwrite('cat_dog.png',res) # 保存图片

1.8 读取视频

vc = cv2.VideoCapture('cxk.mp4')  # 读取视频,传入视频路径
# 检查是否打开正确
if vc.isOpened():
    open, frame = vc.read()
else:
    open = False
while open:
    ret, frame = vc.read()
    if frame is None:
        break
    if ret == True:
        gray = cv2.cvtColor(frame,  cv2.COLOR_BGR2GRAY)  # 将视频中的每一帧图片以灰度图展示
        cv2.imshow('result', gray)
        if cv2.waitKey(50) & 0xFF == ord('q'):  # 视频以50ms每帧显示,或按q键取消
            break
vc.release()
cv2.destroyAllWindows()

二、图像处理 

 2.1 图片阈值

'''==========================图片阈值=========================='''
ret, thresh1 = cv2.threshold(img,127,255,cv2.THRESH_BINARY)
ret, thresh2 = cv2.threshold(img,127,255,cv2.THRESH_BINARY_INV)
ret, thresh3 = cv2.threshold(img,127,255,cv2.THRESH_TRUNC)
ret, thresh4 = cv2.threshold(img,127,255,cv2.THRESH_TOZERO)
ret, thresh5 = cv2.threshold(img,127,255,cv2.THRESH_TOZERO_INV)

titles = ['Original Image','THRESH_BINARY','THRESH_BINARY_INV','THRESH_TRUNC',
         'THRESH_TOZERO','THRESH_TOZERO_INV']
images = [img, thresh1, thresh2, thresh3, thresh4, thresh5]
for i in range(6):
    plt.subplot(2,3,i+1),plt.imshow(images[i],'gray')
    plt.title(titles[i])
    plt.xticks([]),plt.yticks([])
plt.savefig('Lena_threshold.png',dpi=300,bbox_inches='tight')
plt.show()

ret, dst = cv2.threshold(src, thresh, maxval, type)
src: 输入图,只能输入单通道图像,通常来说为灰度图
dst: 输出图
thresh: 阈值
maxval: 当像素值超过了阈值(或者小于阈值,根据type来决定),所赋予的值
**type:**二值化操作的类型,包含以下5种类型:
cv2.THRESH_BINARY: 超过阈值部分取 maxval (最大值),否则取0;
cv2.THRESH_BINARY_INV:THRESH_BINARY的反转;
cv2.THRESH_TRUNC:大于阈值部分设为阈值,否则不变;
cv2.THRESH_TOZERO:大于阈值部分不改变,否则设为0;
cv2.THRESH_TOZERO_INV: THRESH_TOZERO的反转。

2.2 图片平滑

'''==========================图片平滑=========================='''
# 生成带有噪音的图片
rand_data = np.random.randint(100,400,size=60)
for x in rand_data:
    for y in rand_data:
        img[x:x+1,y:y+1, 0] = 255
        img[x:x+1,y:y+1, 1] = 255
        img[x:x+1,y:y+1, 2] = 255
print(rand_data)
# 均值滤波
blur = cv2.blur(img,(3,3))
# 方框滤波
box = cv2.boxFilter(img,-1,(3,3),normalize = False) #normalize = False不进行归一化,卷积核内的数值相加,数值最大为255,True相当于cv2.Blur
# 高斯滤波
gaussian = cv2.GaussianBlur(img,(3,3),1)
# 中值滤波
median = cv2.medianBlur(img,5)
res = np.hstack( (img,box,gaussian,median))
cv2.imwrite('Lena_filter.png',res)

2.3 形态学--腐蚀/膨胀

'''==========================腐蚀/膨胀操作=========================='''
kernel = np.ones((5,5),np.uint8)
erosion = cv2.erode(img,kernel,iterations=1) # iterations=1腐蚀执行1次
dilation = cv2.dilate(img,kernel,iterations=1) # iterations=1膨胀执行1次
'''==========================开/闭操作=========================='''
opening = cv2.morphologyEx(img,cv2.MORPH_OPEN,kernel) #先腐蚀后膨胀
close = cv2.morphologyEx(img,cv2.MORPH_CLOSE,kernel)  #先膨胀后腐蚀
'''==========================梯度运算=========================='''
gradient = cv2.morphologyEx(img,cv2.MORPH_GRADIENT,kernel) # 膨胀-腐蚀
'''==========================礼帽与黑帽=========================='''
tophat = cv2.morphologyEx(img,cv2.MORPH_TOPHAT,kernel)  # 原始输入-开运算结果
blackhat = cv2.morphologyEx(img,cv2.MORPH_BLACKHAT,kernel) # 闭运算-原始输入

 2.4 图像梯度

2.4.1 sobel 算子

'''==========================图像梯度=========================='''
sobelx = cv2.Sobel(img,cv2.CV_64F,dx=1,dy=0,ksize=3)   # 求水平的梯度
sobelx = cv2.convertScaleAbs(sobelx) # 求sobelx梯度的绝对值
sobely = cv2.Sobel(img,cv2.CV_64F,dx=0,dy=1,ksize=3)   # 求竖直的梯度
sobely = cv2.convertScaleAbs(sobely) # 求sobely梯度的绝对值
sobelxy = cv2.addWeighted(sobelx,0.5,sobely,0.5,0) 
res = np.hstack( (img,sobelx,sobely,sobelxy) )
cv2.imwrite('Lena_sobel.png',res)
# 或
# sobelxy = cv2.Sobel(img,cv2.CV_64F,dx=1,dy=1,ksize=3)  # 同时求xy轴的梯度;不建议使用
# sobelxy = cv2.convertScaleAbs(sobelxy) # 求sobelxy梯度的绝对值

 2.4.2 Scharr 算子

'''==========================Scharr算子=========================='''
scharrx = cv2.Scharr(img,cv2.CV_64F,dx=1,dy=0,ksize=3)
scharry = cv2.Scharr(img,cv2.CV_64F,dx=0,dy=1,ksize=3)
scharrx = cv2.convertScaleAbs(scharrx)
scharry = cv2.convertScaleAbs(scharry)
scharrxy = cv2.addWeighted(scharrx,0.5,scharry,0.5,0)

2.4.3 Laplacian 算子

laplacian = cv2.Laplacian(img,cv2.CV_64F)
laplacian = cv2.convertScaleAbs(laplacian)

 2.4.4 三种算子的比较

'''==========================sobel算子=========================='''
sobelx = cv2.Sobel(img,cv2.CV_64F,dx=1,dy=0,ksize=3)   # 求水平的梯度
sobelx = cv2.convertScaleAbs(sobelx) # 求sobelx梯度的绝对值
sobely = cv2.Sobel(img,cv2.CV_64F,dx=0,dy=1,ksize=3)   # 求竖直的梯度
sobely = cv2.convertScaleAbs(sobely) # 求sobely梯度的绝对值
sobelxy = cv2.addWeighted(sobelx,0.5,sobely,0.5,0)
'''==========================Scharr算子=========================='''
scharrx = cv2.Scharr(img,cv2.CV_64F,dx=1,dy=0)
scharry = cv2.Scharr(img,cv2.CV_64F,dx=0,dy=1)
scharrx = cv2.convertScaleAbs(scharrx)
scharry = cv2.convertScaleAbs(scharry)
scharrxy = cv2.addWeighted(scharrx,0.5,scharry,0.5,0)
'''==========================Laplacian算子=========================='''
laplacian = cv2.Laplacian(img,cv2.CV_64F)
laplacian = cv2.convertScaleAbs(laplacian)

res = np.hstack((sobelxy,scharrxy,laplacian))
cv2.imwrite('Lena_SSL.png',res)

三、边缘检测

'''==========================Canny边缘检测=========================='''
canny1 = cv2.Canny(img,80,150)  # 80,150 双阈值(梯度)
canny2 = cv2.Canny(img,50,100)  
res = np.hstack((canny1,canny2))
cv2.imwrite('Lena_canny.png',res)

 2.5 图像金字塔

'''==========================图象金字塔=========================='''
# 高斯金字塔
up = cv2.pyrUp(img)
print(up.shape)
up_down = cv2.pyrDown(up)
print(up_down.shape)
# 拉普拉斯金字塔=img-pyrUp(pyrDown(img))
l_l=img-cv2.pyrUp(cv2.pyrDown(img))
res = np.hstack((img,up_down,l_l))
cv2.imwrite('Lena_Pyr.png',res)

 2.6 图像轮廓

img = cv2.imread('Log.png')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
'''==========================图象轮廓=========================='''
# 为了更高的准确率,先将图片转换成二值图像,
ret,thresh = cv2.threshold(gray,100,255,cv2.THRESH_BINARY)
# cv2.RETR_TREE 得到所有轮廓
draw=img.copy()
contours,binary = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
res = cv2.drawContours(draw,contours,-1,(0,0,225),2)
res = np.hstack((img,res))
cv2.imwrite('Log_Contours.png',res)

2.7 模板匹配

'''==========================模板匹配=========================='''
img = cv2.imread('Lena.png',0)
template = cv2.imread('face.png',0) # 导入匹配模板
h,w = template.shape[:2]
methods = ['cv2.TM_CCOEFF','cv2.TM_CCOEFF_NORMED','cv2.TM_CCORR','cv2.TM_CCORR_NORMED','cv2.TM_SQDIFF','cv2.TM_SQDIFF_NORMED']
for meth in methods:
    img2 = img.copy()
    method = eval(meth)
    print(method)
    res = cv2.matchTemplate(img,template,method) # 模板匹配结果
    min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)
    if method in [cv2.TM_SQDIFF,cv2.TM_SQDIFF_NORMED]:
        top_left = min_loc
    else:
        top_left = max_loc
    bottom_right = (top_left[0] + w, top_left[1] + h)
    cv2.rectangle(img2,top_left,bottom_right,255,2)
    plt.subplot(121),plt.imshow(res, cmap='gray')
    plt.xticks([]),plt.yticks([]) # 隐藏坐标轴
    plt.subplot(122),plt.imshow(img2, cmap='gray')
    plt.xticks([]),plt.yticks([])
    plt.suptitle(meth)
    plt.savefig('f{meth}.png', dpi = 300, bbox_inches='tight')
    plt.show()

 

 

2.8  像素直方图

'''==========================像素直方图=========================='''
img = cv2.imread('Lena.png',cv2.IMREAD_COLOR)  # cv2.IMREAD_GRAYSCALE为灰度图
color=('b','g','r')
for i,col in enumerate(color):
    histr = cv2.calcHist([img],[i],None,[256],[0,256])
    plt.plot(histr,color=col)
    plt.xlim([0,256])#x轴的范围
plt.savefig('hist.png',dpi=300,bbox_inches='tight')
plt.show()

'''=======================mask--像素直方图======================='''
img = cv2.imread('Lena.png',cv2.IMREAD_GRAYSCALE)  # cv2.IMREAD_GRAYSCALE为灰度图
mask = np.zeros(img.shape[:2], np.uint8)
mask[150:400,200:370]=255
mask_img=cv2.bitwise_and(img,img,mask=mask)#图片之间与操作

hist_full = cv2.calcHist([img],[0],None,[256],[0,256])
hist_mask=cv2.calcHist([img],[0],mask,[256],[0,256])
plt.subplot(221), plt.imshow(img, 'gray')
plt.subplot(222), plt.imshow(mask, 'gray')
plt.subplot(223), plt.imshow(mask_img, 'gray')
plt.subplot(224), plt.plot(hist_full), plt.plot(hist_mask)
plt.xlim([0, 256])
plt.savefig('hist_mask.png',dpi=300,bbox_inches='tight')
plt.show()

 2.9 图像均衡化

'''=======================均衡化像素直方图======================='''
img=cv2.imread('clahe.png',0)
plt.subplot(131),plt.plot(cv2.calcHist([img],[0],None,[256],[0,256]))

equ=cv2.equalizeHist(img)
plt.subplot(132),plt.plot(cv2.calcHist([equ],[0],None,[256],[0,256]))

#自适应直方图均衡化
#clipLimit颜色对比度的阈值, titleGridSize进行像素均衡化的网格大小,即在多少网格下进行直方图的均衡化操作
clahe=cv2.createCLAHE(clipLimit=2.0,tileGridSize=(8,8))
res_clahe = clahe.apply(img)
plt.subplot(133),plt.plot(cv2.calcHist([res_clahe],[0],None,[256],[0,256]))

res = np.hstack((img,equ,res_clahe))
cv2.imwrite('clahe_all.png',res)

# plt.ylim([0, 1600])
plt.xlim([0, 256])
plt.savefig('clahe_hist.png',dpi=300,bbox_inches='tight')
plt.show()

参考文献:

OpenCV最详细入门(一)-python(代码全部可以直接运行)_opencv python-优快云博客

OpenCV最详细入门(二)-python(代码全部可以直接运行)_img=cv2.imread('clahe.jpg',0)-优快云博客

【B站最好的OpenCV课程推荐】OpenCV从入门到实战 全套课程(附带课程课件资料+课件笔记)图像处理|深度学习人工智能计算机视觉python+AI_哔哩哔哩_bilibili

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值