python/ opencv图像处理

为便于记忆和以后的使用,特总结该博主博客《Python图像处理》专栏(https://blog.csdn.net/Eastmount),简记函数

读取图像:

img = cv2.imread("file_name",para)
'''
para: cv2.IMREAD_UNCHANGED (图像不可变,估计是在使用的过程中,不能对图像进行处理,只允许显示?)
      cv2.IMREAD_GRAYSCALE (灰度图像)
      cv2.IMREAD_COLOR  (读入彩色图像)
    

显示和关闭图像:

cv2.imshow('window_name',img) #window_name即为给显示窗口起名。
cv2.waitKey(delay)  #等待显示,若只输入cv2.imshow()图像只显示一个窗口,没有图像,我使用delay=1。
cv2.destroyWindow('window_name') #关闭指定窗口,通过window_name指定
cv2.destroyAllWindow()  #关闭所有窗口

保存图像:

cv2.imwrite('img_file',img)  #可增加设定文件保存路径,img_file可设定为demo.jpg, img为读入图像或处理之后的图像。

对图像进行像素级操作(numpy)

###说明###

现实生活中的图像通常为RGB彩色图像,多为三通道图像,即在一张图片中,一个像素点包括三个值,即为RGB值。但在实验图像处理中,多采用单通道图像,即灰度图像。

Gray = 0.2999R+0.587G+0.114B

通过opencv读取的图像,其颜色通道顺序为BGR。若采用opencv读取图像并显示图像,不受影响,但如果使用plt(matplotlib.pyplot)对图像进行显示,则需要将图像转换为RGB顺序。

##########

获取图像像素值的方法

###########彩色图像BGR值#############
B = img[x,y,0]
G = img[x,y,1]
R = img[x,y,2] 
## x,y为图像中的坐标
/
pixel_value = img[x,y]
print(pixel_value)
###pixel_value=[B,G,R]


#############灰度图像即单通道图像##############
gray = img[x,y]
##gray 输出只有一个值

更改像素值

######更改单点像素#######
'''彩色图像'''
img[x,y,0] = B_value
img[x,y,1] = G_value
img[x,y,2] = R_value
#该[x,y]点像素最终呈现出来的颜色为三通道BGR叠加在一起的颜色
///
img[x,y] = [B_value,G_value,R_value]

'''灰色图像'''
img[x,y] = Gray_value

######更改区域像素######
img[x1:x2,y1:y2] = [B_value,G_value,R_value]

numpy像素处理相关

import numpy as np
##读取像素
pixel = img.item(x,y,channel) #channel为0,1,2,即表示B,G,R三通道
##更改像素
img.itemset((x,y,channel),new_pixel_value)

获取图像属性

'''
图像形状
'''
height,width,channels = img.shape  #可分别获取图像的高度,宽度和通道数
height,width = img.shape[:2]
###########
height = img.shape[0]
width = img.shape[1]
channels = img.shape[2]

'''
像素数目
'''
pixel_num = img.size  #pixel_num = height*width*channels

'''
图像类型
'''
img_type = img.dtype  #获取图像的数据类型,通常为uint8,即0~255

图像通道处理

该部分可应用与图像BGR2RBG等类似转换,当然opencv也有直接的函数

'''
图像通道拆分
'''
###one###
B = img[:,:,0]
G = img[:,:,1]
R = img[:,:,2]

###two###
B,G,R = img.split(img)
///
B = cv2.split(img)[0]
G = cv2.split(img)[1]
R = cv2.split(img)[2]

'''
图像通道融合
'''
new_img = cv2.merge([B,G,R])  ##/cv2.merge([channel_1,channel_2,channel_3])可调整颜色通道顺序

new_channel_set = np.zeros((rows,cols),dtype = img.dtype) #自己设定全0通道

图像类型转换

###例如灰度图像,RGB图像,BGR图像(包括但不限于)
cv2.COLOR_BGR2RGB
cv2.COLOR_BGR2GRAY
cv2.COLOR_RGB2GRAY

result =cv2.cvtColor(img,cv2.COLOR_BGR2RGB)  ##可根据实际需要调整

图像灰度化处理

###说明###

灰度化通常是将三通道彩色图像转换为三通道值全部相等的图像即,R=G=B=Gray

(1)最大值灰度处理    Gray = max(R,G,B)

(2)浮点灰度处理       Gray = R*0.30+G*0.59+B*0.11

(3)整数灰度处理       Gray = (R*30+G*59+B*11)/100

(4)移位灰度处理       Gray = (R*28+G*151+B*77)>>8

(5)平均灰度处理      Gray = (R+G+B)/3

(6)加权平均灰度处理    Gray = R*0.999+G*0.587+B*0.114

'''
基于OpenCV的图像灰度化处理
'''
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
#在平时应用过程中,九种常见的颜色空间:BGR、RGB、GRAY、HSV、YCrCb、HLS、XYZ、LAB和YUV
#均可通过opencv进行转换: cv2.cvtColor(img,cv2.COLOR_XXX2XXX)
'''
基于像素操作的图像灰度化处理
'''
#最大值灰度化处理
height = img.shape[0]
width = img.shape[1]
gray_img = np.zeros((height,width,3),np.uint8)
for i in range(height):
    for j in range(width):
        gray = max(img[i,j][0],img[i,j][1],img[i,j][2])
        gray_img[i,j] = np.uint8(gray)
#平均灰度化处理
gray = (int(img[i,j][0])+int(img[i,j][1])+int(img[i,j][2]))/3
#加权平均灰度化处理
gray = 0.30*img[i,j][0]+0.59*img[i,j][1]+0.11*img[i,j][2]

图像平滑

'''
图像平滑是一种区域增强的算法
均值滤波、方框滤波、高斯滤波、中值滤波
'''
###为图像增加噪声操作###
rows,cols,channels = img.shape # rows:图像像素的行数,即可以称之为图像的高度height;同理cols:图像像素的列数,width.
##增加噪声,即为在图像中增加白点或黑点
for i in range(noise_dot_num):
    x = np.random.randint(0,rows)  #产生0~rows的随机数
    x = np.random.randint(0,cols)
    img[x,y,:] = 255    ###img[x,y,:] = 0
'''均值滤波'''
#result = cv2.blur(img,kernel) 
result = cv2.blur(img,(5,5))
'''方框滤波'''
#基本与均值滤波一样,但可设置是否归一化
result = cv2.boxFilter(img,-1,(5,5),normalize = 1)
## -1 表示图像深度,与原图像保持一样;(5,5)即为kernel;normalize=1表明归一化,若未归一化,其周围像素点之和可能大于255,则默认为255.
'''高斯滤波'''
#为周围像素增加权值,根据距离目标像素的距离
result = cv2.GaussianBlur(img,(5,5),0) #(5,5):kernel; 0:sigmaX X方向方差
'''中值滤波'''
#对于消除孤点和线段的干扰十分有用
result = cv2.medianBlur(img,5)  #5:kernel  kernel必须设定为奇数。

图像叠加

'''图像加法'''
#numpy
result = img_1 + img_2  #img_1,img_2大小应相同,即img_1.shape = img_2.shape,去相同未知的像素点相加,当total>255 , total%255

#opencv
result = cv2.add(img_1,img_2)   #if total>255 ,then total=255
'''图像融合'''
result = cv2.addWeighted(img_1,alpha,img_2,beta,gamma)
# result = img_1*alpha + img_2*beta + gamma   gamma:亮度调节

图像缩放 / 图像旋转 / 图像翻转 / 图像平移

'''图像缩放'''
result = cv2.resize(img,(set_width,set_height))
'''or'''
rows,cols = img.shape[:2]  #rows行数即height , cols列数即宽度width
result = cv2.resize(img,(int(cols*weight),int(rows*weight)))
'''or'''  
result = cv2.resize(img,None,fx = 0.5,fy=0.5) #None表示缩放大小,fx,fy表示缩放比例,两者取一就好。
'''图像旋转'''
#getRoationMatrix2D()  warpAffine()
M = cv2.getRoationMatrix2D((cols/2,rows/2),45,1)  #(cols/2,rows/2)旋转中心 45:旋转角度 1:scale
rotated_result = cv2.warpAffine(img,M,(img.shape[1],img.shape[0]))  #M 旋转参数  (img.shape[1],img.shape[0])原始图像大小
'''图像翻转'''
result = cv2.flip(img,0) #以x轴为对称轴翻转
result = cv2.flip(img,1) #以y轴为对称轴翻转 para > 0
result = cv2.flip(img,-1) #以x,y轴为对称轴翻转 para < 0
'''图像平移'''
##类似于图像旋转,只不过这里需要平移参数
M = np.float32([[1,0,x],[0,1,y]])  # 改变x值大小,x>0 则向下平移,反则反之;改变y值大小,y>0则向右平移,反则反之。
pingyi_result = cv2.warpAffine(img,M,(img.shape[1],img.shape[0]))

图像阈值化处理

###说明###
阈值化处理针对灰度图像,故在进行阈值化处理之前,需要先将彩色图像转化为灰度图像。

gray_img = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

########

"""二进制阈值化"""
'''
if pixel_value>thresh:  
    pixel_value = 255
else:
    pixel_value = 0
'''
r,b = cv2.threshold(gray_img,thresh,255,cv2.THRESH_BINARY)
#r : thresh  b即为result_img 。 

"""反二进制阈值化"""
'''
if pixel_value>thresh:
    pixel_value= 0
else:
    pixel_value = 255
'''
r,b = cv2.threshold(gray_img,thresh,255,cv2.THRESH_BINARY_INV)

"""截断阈值化"""
'''
if pixel_value>=thresh:
    pixel_value=thresh
else:
    pixel_value = pixel_value
'''
r,b = cv2.threshold(gray_img,thresh,255,cv2.THRESH_TRUNC)

"""反阈值化为0"""
'''
if pixel_value >=thresh:
    pixel_value = 0
else:
    pixel_value = pixel_value
'''
r,b = cv2.threshold(gray_img,thresh,255,cv2.THRESH_TOZERO_INV)

"""阈值化为0"""
'''
if pixel_value >= thresh:
    pixel_value = pixel_value
else:
    pixel_value = 0
'''
r,b = cv2.threshold(gray_img,thresh,255,cv2.THRESH_TOZERO)

图像腐蚀 and 图像膨胀

'''
图像腐蚀:变细
图像膨胀:加粗
'''
'''图像腐蚀'''
#result = cv2.erode(img,kernel,iterations)
kernel = np.ones((5,5),np.uint8)
result = cv2.erode(img,kernel)   #如果不填写iterations,则默认为1

'''图像膨胀'''
#result = cv2.dilate(img,kernel,iterations)
kernel = np.ones((5,5),np.uint8)
result = cv2.dilate(img,kernel) #如果不填写iterations,则默认为1

图像开运算 and  图像闭运算 and 图像梯度运算 and 图像顶帽运算 and 图像黑帽运算

"""
图像开运算,先对图像进行腐蚀操作,然后进行膨胀操作
可去除图像噪声,并保留原有图像
"""
kernel = np.ones((5,5),np.uint8)
result = cv2.morphologyEx(img,cv2.MORPH_OPEN,kernel)
"""
图像闭运算,先对图像进行膨胀操作,然后进行腐蚀操作
可去除图像中的小黑点,使得图像更加完整圆润
"""
kernel =np.ones((5,5),np.uint8)
result = cv2.morphologyEx(img,cv2.MORPH_CLOSE,kernel)
"""
图像梯度运算
将膨胀图像减去腐蚀图像得到的结果
"""
kernel = np.ones((5,5),np.uint8)
result = cv2.morphologyEx(img,cv2.MORPH_GRADIENT,kernel)
"""
图像顶帽运算
将原图像减去图像开运算的结果,得到图像的噪声
"""
kernel = np.ones((5,5),np.uint8)
result = cv2.morphologyEx(img,cv2.MORPH_TOPHAT,kernel)
"""
图像黑帽运算
将图像闭运算的结果减去原图像,得到图像内部的小孔,或者前景色中的小黑点
"""
kernel = np.ones((5,5),np.uint8)
result = cv2.morphologyEx(img,cv2.MORPH_BLACKHAT,kernel)

基于灰度三维图的黑帽运算

###说明###

本部分还可以学习一下matpltlib画图

##########

# -*- coding: utf-8-*-
import numpy as np
import cv2
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
from matplotlib.ticker import LinearLocator,FormatStrFormatter

img = cv2.imread('img_name')
img = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

#对原始图像进行黑帽运算,可去除受光照不均匀影响,造成背景灰度不均匀的现象
#kernel = np.ones((10,10),np.uint8)
#img = cv2.morphologyEx(img,cv2.MORPH_BLACKHAT,kernel)

imgd = np.array(img)  #image类转numpy类

h = int(img.shape[0])
w = int(img.shape[1])
#开始绘制图像
fig = plt.figure(figsize = (16,12))
ax = fig.gca(projection='3d')
x = np.arange(0,w,1)
y = np.arange(0,h,1)
x,y = np.meshgrid(x,y)
z = imgd
surf = ax.plot_surface(x,y,z,cmap = cm.coolwarm)

ax.set_zlim(-10,255)
ax.zaxis.set_major_locator(LinearLocator(10))  #设置Z轴网格线的疏密
ax.zaxis.set_major_formatter(FormatStrFormatter('%.02f'))

ax.set_xlabel('x',size = 15)
ax.set_ylabel('y',size = 15)
ax.set_zlabel('z',size = 15)
ax.set_title('surface plot',weight = 'bold',size = 20)

fig.colorbar(surf,shrink = 0.6,aspect = 8)
plt.show()

灰度直方图

###说明###

灰度直方图,自我理解,即为统计图像中,每个不同像素值所出现的总次数,从而统计全部的像素以及所对应的出现频率。

##########

'''
plt绘制直方图
'''
import matplotlib.pyplot as plt
img_process = gray_img.ravel()    #将二维数组转化为一维数组 
plt.hist(img_process,256)      #img_process:为图像的一维数组形式;256:[0,255]
plt.show()
'''
opencv绘制直方图
hist = cv2.calcHist(images,channels,mask,histSize,ranges,accumulate)
#channels:图像的通道,对于彩色三通道图像来说,[0],[1],[2]来表示三个通道;mask:None,当针对图像的一部分进行统计的时候,可以使用。
#histSize: 统计分类数,对于彩色图像来说,通常设置为256,即[0,255]
#ranges:像素值范围 [0,255]
#accumulate:累计叠加标识,默认为False
'''
#对于彩色图像
img = cv2.imread('img_name')
histb = cv2.calcHist(img,[0],None,[256],[0,255])
histg = cv2.calcHist(img,[1],None,[256],[0,255])
histr = cv2.calcHist(img,[2],None,[256],[0,255])
#显示
plt.plot(histb,color='')
plt.plot(histg,color = 'g')
plt.plot(histr,color = 'r')
plt.show()

图像仿射变换 and 图像透视变换

###说明###

图像仿射和图像透视的不同,个人理解,图像在仿射变换之后,仍然保持其横平竖直的变化,直线还是直线,平行依旧平行;而透视变换,运行对原始图像规则进行破坏。

##########

'''
图像仿射变换
M = cv2.getAffineTransform(pos1,pos2)
result = cv2.warpAffine(img,M,(img.shape[1],img.shape[0]))
'''
pos1 = np.float32([[],[],[]])  ##[]中填写原始图像坐标
pos2 = np.float32([[],[],[]])  ##[]中填写变换图像坐标
rows,cols = img.shape[:2]
M = cv2.getAffineTransform(pos1,pos2)
result = cv2.warpAffine(img,M,(cols,rows))
'''
图像透视变换
M = cv2.getPerspectiveTransform(pos1,pos2)
result = cv2.warpPerspective(img,M,(img.shape[1],img.shape[0]))
'''
###pos1最好选取待选取图像的区域,由四点坐标来确定区域位置,pos2为变换之后的图像位置,同样为四点坐标,自我认为,最好将待选取图像铺设完整整个图像位置.
pos1 = np.float32([[],[],[],[]])
pos2 = np.float32([[],[],[],[]])
M = cv2.getPerspectiveTransform(pos1,pos2)
result = cv2.warpPerspective(img,M,(img.shape[1],img.shape[0]))

图像灰度化线性变换

###说明###

图像灰度化线性变换通过简历灰度线性映射来调整原始图像的灰度,从而改善图像的质量,凸显图像的细节,提高图像的对比度。  result = A*img+ B

#########

'''
图像灰度线性变换
result = a*gray_img+b
'''
#图像灰度上移变换   a=1,b=50   图像灰度值上移,提高了图像的亮度
height = gray_img.shape[0]
width = grar_img.shape[1]

result = np.zeros((height,width),np.uint8)
for i in range(height):
    for j in range(width):
        if (int(gray_img[i,j]+50)>255:
            gray = 255
        else:
            gray = int(gray_img[i,j]+50)
        result[i,j] = np.uint8(gray)
#图像对比度增强变换  a=1.5,b=0
gray = int(gray_img[i,j]*1.5)
#图像对比度减弱变换  a=0.8,b=0
gray = int(gray_img[i,j]*0.8)  #图像灰度值变小,图像减弱
#图像灰度反色变换  将原图像像素值进行反转,即黑色变为白色,白色变为黑色
gray = 255-gray_img[i,j]

图像灰度化非线性变换

'''
图像灰度化非线性变换:result = gray_img*gray_img/255
'''
gray = int(gray_img[i,j]*gray_img[i,j])/255
'''
图像灰度对数变换
有利于增强图像较暗区域对比度,可增强暗部细节,从而用来扩展被压缩的高值图像中的较暗像素。
'''
#gray = c*log(1+gray_img)  对夜间拍摄照片,可提升图像细节,提升对比度
def log(c,gray_img):
    gray = c*np.log(1.0+gray_img)
    #gray = np.uint8(output+0.5)
    return gray
'''
图像灰度伽玛变换:result = c*gray_img^gamma
'''
#对于图像对比度偏低,并且整体亮度值偏高(照片过曝)情况下的图像增强效果明显。
def gamma(gray_img,c,gamma):
    lut = np.zeros(256,dtype = np.float32)
    for i in range(256):
        lut[i] = c*gray_img^gamma
    result = cv2.LUT(gray_img,lut)
    #result = np.uint8(result+0.5)
    return result

图像锐化边缘检测处理

'''
Roberts算子
常用来处理具有陡峭的低噪声图像,当图像边缘接近于正负45度时,该算法处理效果更理想。
缺点是对边缘的定位不太准确,提取的边缘线条较粗
'''
#Roberts算子
kernelx = np.array([[-1,0],[0,1]],dtype = int)
kernely = np.array([[0,-1],[1,0]],dtype = int)
x = cv2.filter2D(gray_img,cv2.CV_165,kernelx)
y = cv2.filter2D(gray_img,cv2.CV_165,kernely)
#转uint8
absX = cv2.convertScaleAbs(x)
absY = cv2.convertScaleAbs(y)
Roberts_img = cv2.addWeighted(absX,0.5,absY,0.5,0)
'''
Prewitt算子
采用3x3模板,其边缘检测结果在水平方向和垂直方向均比Roberts算子更加明显。
适合噪声较多、灰度渐变的图像
'''
###相对Roberts算子,就只有设置核的时候不一样
kernelx = np.array([[1,0,-1],[1,0,-1],[1,0,-1]])
kernely = np.array([[-1,-1,-1],[0,0,0],[1,1,1]])
'''
Sobel算子
边缘定位更加准确,常用于噪声较多,灰度渐变的图像
'''
x = cv2.Sobel(gray_img,cv2.CV_165,1,0)
y = cv2.Sobel(gray_img,cv2.CV_165,0,1)
absX = cv2.convertScaleAbs(x)
absY = cv2.convertScaleAbs(y)
Sobel_img = cv2.addWeighted(absX,0.5,absY,0.5,0)
'''
Laplacian算子
常用于图像增强和边缘提取
'''
result = cv2.Laplacian(gray_img,cv2.CV_165,ksize = 3)
Laplacian_img = cv2.convertScaleAbs(result)
'''
Scharr算子
相较于Sobel算子,准确率更高
'''
x = cv2.Scharr(gray_img,cv2.CV_32F,1,0)
y = cv2.Scharr(gray_img,cv2.CV_32F,0,1)
absX = cv2.convertScaleAbs(x)
absY = cv2.convertScaleAbs(y)
Scharr_img = cv2.addWeighted(absX,0.5,absY,0.5,0)
'''
Canny算子
'''
Gaussian_img = cv2.GaussianBlur(gray_img,(3,3),0)
Canny_img = cv2.Canny(Gaussian_img,50,150)
'''
LOG算子
'''
Gaussian_img = cv2.GaussianBlur(gray_img,(3,3),0)
result_img = cv2.Laplacian(Gaussian_img,cv2.CV_165,ksize = 3)
LOG_img = cv2.convertScaleAbs(result_img)
#######
#边缘检测算法主要是基于图像强度的一阶和二阶导数,但导数通常对噪声很敏感,因此需要采用滤波器来过滤#噪声,并调用图像增强或阈值化算法进行处理,最后再进行边缘检测。
#######

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值