opencv学习(一)
一、基础知识
1、图像加载与保存
什么是图片:结构化存储的数据信息
图像属性:通道数目、高与宽、像素数据、图像类型
import cv2 as cv import numpy as np#科学计数的包 def vedio_demo(): capture=cv.VideoCapture(0) while(True): ret,frame=capture.read() frame=cv.flip(frame,1) cv.imshow("video",frame) c=cv.waitKey(50) if c== 27: break def get_image_info(image): print(type(image))#<class 'numpy.ndarray'> #n维数组 print(image.shape) print(image.size) print(image.dtype) pixel_data=np.array(image) print(pixel_data) src=cv.imread("D:/lena.jpg") cv.namedWindow("input image:",cv.WND_PROP_AUTOSIZE) cv.imshow("input image:",src) get_image_info(src) cv.waitKey(0) cv.destroyWindow()
2、Numpy数组操作
import cv2 as cv import numpy as np#科学计数的包 def access_pixels(image): print(image.shape) height=image.shape[0] width=image.shape[1] channels=image.shape[2] print("width:%s,height:%dsS,channel:%s"%(width,height,channels)) for row in range(height): for col in range(width): for c in range(channels): pv=image[row,col,c] image[row,col,c]=255-pv cv.imshow("pixels_demo",image) def inverse(image): dst=cv.bitwise_not(image) cv.imshow("inverse demo",dst) def create_image(): m1=np.ones([3,3],np.float) m1.fill(122222.44) print(m1) m2=m1.reshape([1,9])#reshape作用 print(m2) ''' img=np.ones([400,400,1],np.uint8) img=img*255 cv.imshow("image",img) img=np.zeros([400,400,3],np.uint8) img[:,:,2]=np.ones([400,400])*255 通过np进行各个通道赋值 cv.imshow("new image",img) ''' src=cv.imread("D:/lena.jpg")# blue green red cv.namedWindow("input image:",cv.WND_PROP_AUTOSIZE) cv.imshow("input image:",src) t1=cv.getTickCount() inverse(src) t2=cv.getTickCount() time=(t2-t1)/cv.getTickFrequency() print("time:%s ms"%time) cv.waitKey(0) cv.destroyWindow()
3、色彩空间
# 颜色空间转换,从bgr到gray,hsv,yuv,ycrcb
def color_space_demo(image):
gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
cv.imshow("gray", gray)
hsv = cv.cvtColor(image, cv.COLOR_BGR2HSV)
cv.imshow("hsv", hsv)
yuv = cv.cvtColor(image, cv.COLOR_BGR2YUV)
cv.imshow("yuv", yuv)
ycrcb = cv.cvtColor(image, cv.COLOR_BGR2YCrCb)
cv.imshow("ycrcb", ycrcb)
# 从视频中提取指定颜色范围,并将其置为白,其余置为黑
def extract_object_demo():
capture = cv.VideoCapture("cv.gif")
while True:
ret, frame = capture.read()
if ret is False: # 如果没有获取到视频帧则返回false
break
hsv = cv.cvtColor(frame, cv.COLOR_BGR2HSV)
lower_hsv = np.array([0, 43, 46]) # hsv中h,s,v的最小值
upper_hsv = np.array([50, 255, 255]) # hsv中的h,s,v最大值
# 提取指定范围颜色,保留指定范围颜色, 其余置为黑(0)
mask = cv.inRange(hsv, lowerb=lower_hsv, upperb=upper_hsv) # 用inRange函数提取指定颜色范围,这里对hsv来处理
cv.imshow("video", frame)
cv.imshow("mask", mask)
c = cv.waitKey(40)
if c == 27:
break
# 对图片三个通道颜色提取并放在三张图片中
def channels_split_merge(image):
b, g, r = cv.split(image) # b通道提取时,对该通道颜色保留,其余通道置为0
cv.imshow("blue", b)
cv.imshow("green", g)
cv.imshow("red", r)
changed_image = image.copy()
changed_image[:, :, 2] = 0 # 将r通道颜色全部置为0
cv.imshow("changed_image", changed_image)
merge_image = cv.merge([b, g, r])
cv.imshow("merge_image", merge_image)
4、像素运算


import cv2 as cv import numpy as np # 对图像像素级别的加减乘除 def add_demo(m1, m2): dst = cv.add(m1, m2) cv.imshow("add_demo", dst) def subtract_demo(m1, m2): dst = cv.subtract(m1, m2) cv.imshow("subtract_demo", dst) def divide_demo(m1, m2): dst = cv.divide(m1, m2) cv.imshow("divide_demo", dst) def multiply_demo(m1, m2): dst = cv.multiply(m1, m2) cv.imshow("multiply_demo", dst) # 图像的逻辑运算,:AND,OR,NOT,XOR def logic_demo(m1, m2): image = cv.imread("CrystalLiu2.jpg") cv.imshow("image1",image) dst = cv.bitwise_not(image) cv.imshow("logic_demo", dst) def contrast_brightness_demo(image, c, b): h, w, ch = image.shape blank = np.zeros([h, w, ch], image.dtype) # 图像混合,c, 1-c为这两张图片的权重 dst = cv.addWeighted(image, c, blank, 1-c, b) cv.imshow("contrast_brightness_demo", dst) # 对照片像素做均值方差 def others(m1, m2): M1 = cv.mean(m1) M2 = cv.mean(m2) print(M1) print(M2) mean1, dev1 = cv.meanStdDev(m1) print("均值:",mean1,"方差:", dev1) if __name__ == '__main__': print("----------Hello World!----------") src1 = cv.imread("../images/01.jpg") src2 = cv.imread("../images/02.jpg") print(src1.shape) print(src2.shape) cv.namedWindow("image1", cv.WINDOW_AUTOSIZE) # 创建窗口, 窗口尺寸自动调整 cv.imshow("image1", src1) cv.imshow("image2", src2) # add_demo(src1, src2) # subtract_demo(src1, src2) # divide_demo(src1, src2) # multiply_demo(src1,src2) # others(src1, src2) # logic_demo(src1, src2) src = cv.imread("../images/CrystalLiu2.jpg") contrast_brightness_demo(src,1.3, 80) cv.waitKey(0) cv.destroyAllWindows()
5、ROI与泛红填充


import cv2 as cv import numpy as np#科学计数的包 def fill_color_demo(image): copyImg=image.copy() h,w=image.shape[:2] mask=np.zeros([h+2,w+2],np.uint8) # mask的参数必须是+2和uint8 # why?从0,0开始扫描,保证周边的像素都能被扫描 多数基于8的扫描算法 cv.floodFill(copyImg,mask,(30,30),(0,255,255),(100,100,100),(50,50,50),cv.FLOODFILL_FIXED_RANGE) ''' 参数: 原图,mask,起始点,填充的颜色,起始点减去该值作为最低值,起始点加上该值作为最高值,彩色图模式 泛红填充: -FLOODFILL_FIXED_RANGE-改变图像,泛红填充 -MASK_ONLY-不改变图像,只填充遮罩层本身(mask=0),忽略新的颜色值参数 例:(30,30)这个像素点的值相减相加 ''' cv.imshow("fill_color_demo",copyImg) def fill_binary(): image=np.zeros([400,400,3],np.uint8) image[100:300,100:300:]=255 cv.imshow("fill_binary",image) mask=np.ones([402,402,1],np.uint8)#mask一定要初始化1 mask[101:301,101:301]=0#填充一定要初始化0 #floodfill只有没填充的才会被填上!!!! cv.floodFill(image,mask,(200,200),(200,20,255),cv.FLOODFILL_MASK_ONLY) cv.imshow("filled binary",image) def roi_test(src): face=src[100:150,200:500] gray=cv.cvtColor(face,cv.COLOR_BGR2GRAY) cv.imshow("gray:",gray) back_face=cv.cvtColor(gray,cv.COLOR_GRAY2BGR) cv.imshow("back_face:",back_face) src[100:150,200:500]=back_face cv.imshow("face:",src) # gray→bgr 需要通道数一样,只是加了通道数,并不知道原图的彩色矩阵 ''' ROI操作 face=src[]//起始位置结束位置,指定ROI范围 h w 得到gray图 gray转换bgr 再相结合 ''' src1=cv.imread("D:/opencvimage/01.jpg") src2=cv.imread("D:/opencvimage/02.jpg") src = cv.imread("D:/opencvimage/lena.jpg") # roi_test(src) fill_binary() cv.waitKey(0) cv.destroyWindow()
6、模糊操作


def blur_demo(image): dst=cv.blur(image,(5,5))#卷积层为5*5,均值模糊 cv.imshow("bur_demo",dst) def mediu_blur_demo(image): dst=cv.medianBlur(image,5) #中值模糊 对椒盐噪声友好 cv.imshow("mediu_bur_demo",dst) #自定义的模糊,锐化,总和为0——做边缘梯度 总和为1——做增强 def custom_blur_demo(image): kernel=np.ones([5,5],np.float32)/25 #例:随便定义一个算子,锐化立体 kernel=np.array([[0,-1,0],[-1,5,-1],[0,-1,0]],np.float32) dst=cv.filter2D(image,-1,kernel) #ddepth默认-1 cv.imshow("custom_bur_demo",dst)
7、高斯滤波

''' 一些图像知识: 1. 噪声:主要有三种: 椒盐噪声(Salt & Pepper):含有随机出现的黑白亮度值。 脉冲噪声:只含有随机的正脉冲和负脉冲噪声。 高斯噪声:含有亮度服从高斯或正态分布的噪声。高斯噪声是很多传感器噪声的模型,如摄像机的电子干扰噪声。 2. 滤波器:主要两类:线性和非线性 线性滤波器:使用连续窗函数内像素加权和来实现滤波,同一模式的权重因子可以作用在每一个窗口内,即线性滤波器是空间不变的。 如果图像的不同部分使用不同的滤波权重因子,线性滤波器是空间可变的。因此可以使用卷积模板来实现滤波。 线性滤波器对去除高斯噪声有很好的效果。常用的线性滤波器有均值滤波器和高斯平滑滤波器。 (1) 均值滤波器:最简单均值滤波器是局部均值运算,即每一个像素只用其局部邻域内所有值的平均值来置换. (2) 高斯平滑滤波器是一类根据高斯函数的形状来选择权值的线性滤波器。 高斯平滑滤波器对去除服从正态分布的噪声是很有效的。 非线性滤波器: (1) 中值滤波器:均值滤波和高斯滤波运算主要问题是有可能模糊图像中尖锐不连续的部分。 中值滤波器的基本思想使用像素点邻域灰度值的中值来代替该像素点的灰度值,它可以去除脉冲噪声、椒盐噪声同时保留图像边缘细节。 中值滤波不依赖于邻域内与典型值差别很大的值,处理过程不进行加权运算。 中值滤波在一定条件下可以克服线性滤波器所造成的图像细节模糊,而对滤除脉冲干扰很有效。 (2) 边缘保持滤波器:由于均值滤波:平滑图像外还可能导致图像边缘模糊和中值滤波:去除脉冲噪声的同时可能将图像中的线条细节滤除。 边缘保持滤波器是在综合考虑了均值滤波器和中值滤波器的优缺点后发展起来的,它的特点是: 滤波器在除噪声脉冲的同时,又不至于使图像边缘十分模糊。 过程:分别计算[i,j]的左上角子邻域、左下角子邻域、右上角子邻域、右下角子邻域的灰度分布均匀度V; 然后取最小均匀度对应区域的均值作为该像素点的新灰度值。分布越均匀,均匀度V值越小。v=<(f(x, y) - f_(x, y))^2 ''' import cv2 as cv import numpy as np def blur_demo(image): # dst = cv.blur(image, (5, 5)) # 卷积核为5x5,均值模糊 # dst = cv.medianBlur(image, 5) # 中值模糊,对椒盐噪声去噪较好 # 自定义滤波器 # kernel = np.ones([5, 5], np.float32) / 25 # 内核大小 kernel = np.array([[0, -1, 0], [-1, 5, -1], [0, -1, 0]], np.float32) # 锐化算子 # filter2D(src, ddepth(图像深度,-1表示默认和src一样深度), kernel, dst=None, anchor=None(锚点,卷积核中心), delta=None, borderType=None) dst = cv.filter2D(image, -1, kernel=kernel) # 二维滤波器 cv.imshow("blur_demo", dst) def clamp(pv): if pv > 255: return 255 elif pv < 0: return 0 else: return pv def gaussian_noise(image): # 加高斯噪声 h, w, c = image.shape for row in range(h): for col in range(w): s = np.random.normal(0, 20, 3) # normal(loc=0.0, scale=1.0, size=None),均值,标准差,大小 b = image[row, col, 0] g = image[row, col, 1] r = image[row, col, 2] image[row, col, 0] = clamp(b + s[0]) image[row, col, 1] = clamp(g + s[1]) image[row, col, 2] = clamp(r + s[2]) cv.imshow("gaussian_noise", image)
浙公网安备 33010602011771号