计算机视觉图像的基本操作

图像 计算机中图像就是由像素点组成。 RGB表示颜色通道,R红色G绿色B蓝色,[0-255]表示该像素点的亮度。 黑白图像只有一个通道表示亮度。 图像是500*500,则RGB三个通道均是500*500的矩阵,一个图像则为[500,500,3]。 数据读取-图像 cv2.IMREAD_COLOR:彩色图像 cv2.IMREAD_GRAYSCALE:灰色图像 import cv2 #OpenCv

图像

  1. 计算机中图像就是由像素点组成。
  2. RGB表示颜色通道,R红色G绿色B蓝色,[0-255]表示该像素点的亮度。
  3. 黑白图像只有一个通道表示亮度。
  4. 图像是500*500,则RGB三个通道均是500*500的矩阵,一个图像则为[500,500,3]。

数据读取-图像

cv2.IMREAD_COLOR:彩色图像

cv2.IMREAD_GRAYSCALE:灰色图像

import cv2                      #OpenCv,有很多计算机视觉需要的的算法;opencv读取的格式是BGR
import matplotlib.pyplot as plt #Pyplot包含一系列绘图函数的相关函数,用as给它设置一个别名plt
import numpy as np              #支持大量的维度数组与矩阵运算 用as给其设置别名np
#%matplotlib inline             #用它可以省略plt.show(),vscode用不了


def cv_show(name,img):      #定义一个函数,更方便的显示图像
    cv2.imshow(name,img)    #图像的显示,也可以创建多个窗口
    cv2.waitKey(0)          #等待时间,毫秒级,0表示任意键终止
    cv2.destroyAllWindows()


img=cv2.imread('cat.jpg')   #显示一个BGR图像
cv2.imshow('image',img)
cv2.waitKey(0)
cv2.destroyAllWindows



img=cv2.imread('cat.jpg',cv2.IMREAD_GRAYSCALE)  #显示一个灰度图像
cv2.imshow('image',img)
cv2.waitKey(0)
cv2.destroyAllWindows

cv2.imwrite('mycat.png',img)    #保存图片

print(img.shape)             #图像基本数值

print(img)                   #图片每一个像素点(矩阵形式)

print(type(img))             #查看图片底层格式

print(img.size)              #计算图片像素点个数

print(img.dtype)             #图像数据类型

截取部分图像数据

img=cv2.imread('cat.jpg')
cat=img[0:200,0:200]         #截取一段图像
cv_show('cat',cat)           #显示截取图像的彩色图

颜色通道提取

B,G,R=cv2.split(img)
print(B)
print(B.shape)
img=cv2.merge((B,G,R))
print(img.shape)

cur_img=img.copy()        #只保留R通道
cur_img[:,:,0]=0
cur_img[:,:,1]=0
cv_show('R',cur_img)


cur_img=img.copy()        #只保留G通道
cur_img[:,:,0]=0
cur_img[:,:,2]=0
cv_show('G',cur_img)

cur_img=img.copy()        #只保留B通道
cur_img[:,:,1]=0
cur_img[:,:,2]=0
cv_show('B',cur_img)

数据读取-视频

cv2.VideoCapture可以捕获摄像头,用数字来控制不同的设备,例如0,1。

如果是视频文件,直接指定好路径即可。

import cv2               
import matplotlib.pyplot as plt    
import numpy as np


#播放一个灰度视频
vc = cv2.VideoCapture('test.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(10) & 0xFF == 27:
            break
vc.ralease()
cv2.destroyAllWindows()



#显示一个彩色视频
vc = cv2.VideoCapture('test.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:
        cv2.imshow('result',frame)
        if cv2.waitKey(10) & 0xFF == 27:
            break
vc.ralease()
cv2.destroyAllWindows()

边界填充

BORDER_REPLICATE:复制法,也就是复制最边缘像素。

BORDER_REFLECT:反射法,对图像中的像素在两边进行复制 fedcba | abcdefgh | hgfedcb

BORDER_REFLECT_101:反射法,也就是以最边缘像素为轴,对称, gfedcb | abcdefgh | gfedcba

BORDER_WRAP:外包装法 cdefgh | abcdefgh | abcdefg

BORDER_CONSTANT:常量法,常数值填充。

import cv2
import numpy as np
import matplotlib.pyplot as plt  

img=cv2.imread('cat.jpg') 
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.show()

运行结果:

数值计算 

import cv2
import numpy as np
import matplotlib.pyplot as plt

img_cat=cv2.imread('cat.jpg')
img_dog=cv2.imread('dog.jpg')

img_cat2=img_cat+10                         #直接相加,两数和超过255时 结果为 两数和 % 256
print(img_cat[:5,:,0])
print(img_cat2[:5,:,0])
print((img_cat+img_cat2)[:5,:,0])

print(cv2.add(img_cat,img_cat2)[:5,:,0])        #用cv2.add相加时,两数和超过255时 结果为255        



# print(img_cat+img_dog)      #shape不同时,不能相加
print(img_cat.shape)
img_dog=cv2.resize(img_dog,(500,414))       #将'dog.jpg'的shape改成和'cat.jpg'一致
print(img_dog.shape)

res=cv2.addWeighted(img_cat,0.4,img_dog,0.6,0)  #将'cat.jpg'和'dog.jpg'融合。'cat.jpg'占比0.4;'dog.jpg'占比0.6;提亮值为0。

plt.imshow(res)
plt.show()

运行结果:

res=cv2.resize(img_cat,(0,0),fx=3,fy=1)         #将图片宽伸长三倍,高不变
plt.imshow(res)
plt.show()

 运行结果:

res=cv2.resize(img_cat,(0,0),fx=1,fy=3)         #将图片宽不变,高伸长三倍
plt.imshow(res)
plt.show()

运行结果 :

形态学

腐蚀操作

腐蚀操作所用函数为cv2.erode(),确定盒子大小的函数是np.ones()。

import cv2              
import matplotlib.pyplot as plt    
import numpy as np

def cv_show(name,img):      
    cv2.imshow(name,img)    
    cv2.waitKey(0)          
    cv2.destroyAllWindows()


#腐蚀操作
img = cv2.imread('dige.png')
cv_show('img',img)
kernel=np.ones((5,5),np.uint8)
erosion=cv2.erode(img,kernel,iterations=1)#迭代 1 次
cv_show('erosion',erosion)

原图:

 腐蚀操作,迭代1次后:

对圆进行腐蚀操作:

pie=cv2.imread('pie.png')
cv_show('pie',pie)
kernel=np.ones((30,30),np.uint8)
erosion_1=cv2.erode(pie,kernel,iterations=1)
erosion_2=cv2.erode(pie,kernel,iterations=2)
erosion_3=cv2.erode(pie,kernel,iterations=3)
res=np.hstack((erosion_1,erosion_2,erosion_3))
cv_show('res',res)

原图:

分别迭代           1                                                  2                                                        3

 膨胀操作

腐蚀操作所用函数为cv2.dilate()

img = cv2.imread('dige.png')
cv_show('img',img)
kernel=np.ones((5,5),np.uint8)
dige_erosion=cv2.erode(img,kernel,iterations=1)
dige_dilate=cv2.dilate(dige_erosion,kernel,iterations=1)
cv_show('dilate',dige_dilate)

 原图:

 膨胀操作,迭代一次后:

对圆进行膨胀操作:

pie=cv2.imread('pie.png')
cv_show('pie',pie)
kernel=np.ones((30,30),np.uint8)
dilate_1=cv2.dilate(pie,kernel,iterations=1)
dilate_2=cv2.dilate(pie,kernel,iterations=2)
dilate_3=cv2.dilate(pie,kernel,iterations=3)
res=np.hstack((dilate_1,dilate_2,dilate_3))
cv_show('res',res)

原图:

分别 迭代                1                                                      2                                                    3

开运算与闭运算

开运算:先腐蚀后膨胀

闭运算:先膨胀后腐蚀

import cv2
import numpy as np
import matplotlib.pyplot as plt

#开运算:先腐蚀后膨胀
def cv_show(name,img):
    cv2.imshow(name,img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

img=cv2.imread('dige.png')
cv_show('yuantu',img)                     #原图
kernel=np.ones((5,5),np.uint8)
opening=cv2.morphologyEx(img,cv2.MORPH_OPEN,kernel)
cv_show('opening',opening)              #先腐蚀后膨胀结果图


#闭运算:先膨胀后腐蚀
img=cv2.imread('dige.png')
cv_show('yuantu',img)                     #原图
kernel=np.ones((5,5),np.uint8)
closing=cv2.morphologyEx(img,cv2.MORPH_CLOSE,kernel)
cv_show('closing',closing)              #先膨胀后腐蚀结果图

原图:

开运算结果图:

 闭运算结果图:

 梯度运算

梯度=膨胀-腐蚀

#梯度运算
#梯度=膨胀—腐蚀
pie=cv2.imread('pie.png')

kernel=np.ones((7,7),np.uint8)
dilate=cv2.dilate(pie,kernel,iterations=5)      #膨胀5次
ersion=cv2.erode(pie,kernel,iterations=5)       #腐蚀5次

res=np.hstack((dilate,ersion))
cv_show('res',res)

gradient=cv2.morphologyEx(pie,cv2.MORPH_GRADIENT,kernel)
cv_show('gradient',gradient)

将原图分别膨胀5次和腐蚀5次后的结果图:

 梯度运算结果图:

 礼帽与黑帽

礼帽:原始输入-开运算结果

img=cv2.imread('dige.png')
tophat=cv2.morphologyEx(img,cv2.MORPH_TOPHAT,kernel)
cv_show('tophat',tophat)

结果图:

黑帽:闭运算结果-原始输入

img=cv2.imread('dige.png')
blackhat=cv2.morphologyEx(img,cv2.MORPH_BLACKHAT,kernel)
cv_show('blackhat',blackhat)

结果图:

 三种梯度计算的算子

Sobel算子

 dst=cv2.Sobel(src,ddepth,dx,dy,ksize)

  • ddepth:图像的深度
  • dx和dy分别表示水平和竖直方向
  • ksize是Sobel算子的大小

img=cv2.imread('D:\pythontupian\pie.png',cv2.IMREAD_GRAYSCALE)
cv2.imshow('img',img)
cv2.waitKey()
cv2.destroyAllWindows()

def cv_show(img,name):
    cv2.imshow(name,img)
    cv2.waitKey()
    cv2.destroyAllWindows()

sobelx=cv2.Sobel(img,cv2.CV_64F,1,0,ksize=3)
cv_show(sobelx,'sobelx')

                           原图                                                                    只计算了右-左且未取绝对值   

 

白到黑是正数,黑到白就是负数了,所有的负数会被截断成0,所以要取绝对值。

sobelx=cv2.Sobel(img,cv2.CV_64F,1,0,ksize=3)
sobelx=cv2.convertScaleAbs(sobelx)      #取绝对值
cv_show(sobelx,'sobelx')

sobely=cv2.Sobel(img,cv2.CV_64F,0,1,ksize=3)
sobely=cv2.convertScaleAbs(sobely)
cv_show(sobely,'sobely')

                                                              下-上的结果截图

 分别计算x和y,再求和

sobelxy=cv2.addWeighted(sobelx,0.5,sobely,0.5,0)
cv_show(sobelxy,'sobelxy')

 直接计算(不建议)

sobelxy=cv2.Sobel(img,cv2.CV_64F,1,1,ksize=3)
sobelxy=cv2.convertScaleAbs(sobelxy)
cv_show(sobelxy,'sobelxy')

"lena" 图片示例:

img=cv2.imread('D:\pythontupian\lena.jpg',cv2.IMREAD_GRAYSCALE)
cv_show(img,'img')
sobelx=cv2.Sobel(img,cv2.CV_64F,1,0,ksize=3)
sobelx=cv2.convertScaleAbs(sobelx)
sobely=cv2.Sobel(img,cv2.CV_64F,0,1,ksize=3)
sobely=cv2.convertScaleAbs(sobely)
sobelxy=cv2.addWeighted(sobelx,0.5,sobely,0.5,0)
cv_show(sobelxy,'sobelxy')

                    原图                                                        先计算右-左,再计算下-上,最后结果相加。

img=cv2.imread('D:\pythontupian\lena.jpg',cv2.IMREAD_GRAYSCALE)
sobelxy=cv2.Sobel(img,cv2.CV_64F,1,1,ksize=3)
sobelxy=cv2.convertScaleAbs(sobelxy)
cv_show(sobelxy,'sobelxy')

                                                                 直接计算梯度

 scharr算子

img=cv2.imread('D:\pythontupian\lena.jpg',cv2.IMREAD_GRAYSCALE)
scharrx=cv2.Scharr(img,cv2.CV_64F,1,0)
scharrx=cv2.convertScaleAbs(scharrx)
scharry=cv2.Scharr(img,cv2.CV_64F,0,1)
scharry=cv2.convertScaleAbs(scharry)
scharrxy=cv2.addWeighted(scharrx,0.5,scharry,0.5,0)

laplacian算子

img=cv2.imread('D:\pythontupian\lena.jpg',cv2.IMREAD_GRAYSCALE)
laplacian=cv2.Laplacian(img,cv2.CV_64F)
laplacian=cv2.convertScaleAbs(laplacian)

 三种算子计算结果比较

res=np.hstack((sobelxy,scharrxy,laplacian))
cv_show(res,'res')

                            Sobel                                          scharr                                      laplacian

图像平滑处理

 均值滤波

简单的平均卷积操作

import cv2
import matplotlib.pyplot as plot
import numpy as np

img=cv2.imread('D:\pythontupian\lenaNoise.png')

def  cv_show(name,img):
    cv2.imshow(name,img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    
#原图
cv_show('img',img)

#均值滤波
#简单的平均卷积操作
blur=cv2.blur(img,(3,3))
cv_show('blur',blur)

 原图:

 结果图:

 方框滤波

基本和均值一样,可以选择归一化

#基本和均值一样,可以选择归一化
box=cv2.boxFilter(img,-1,(3,3),normalize=True)
cv_show('box',box)

结果图:

 不选择归一化的话很容易越界

#未选择归一化,越界后的结果
box=cv2.boxFilter(img,-1,(3,3),normalize=False)
cv_show('box',box)

越界结果图:

高斯滤波

高斯模糊的卷积核里的数值是满足高斯分布,相当于更重视中间的 

#高斯滤波
#高斯模糊的卷积核里的数值是满足高斯分布,相当于更重视中间的
aussian=cv2.GaussianBlur(img,(5,5),1)
cv_show('aussian',aussian)

结果图:

中值滤波

 相当于用中值代替

#中值滤波
#相当于用中值代替
median=cv2.medianBlur(img,5)
cv_show('median',median)

结果图:

 

 展示均值、高斯、中值滤波结果:

#展示所有结果
res=np.hstack((blur,aussian,median),)
cv_show('res',res)

 

 

 

知秋君
上一篇 2024-07-08 16:36
下一篇 2024-07-08 16:02

相关推荐