opencv-python使用

 

  .jpg 格式为有损格式,若图像array保存为 .jpg 格式,再读入时,array内容和保存前的会又误差;若需要精准数据,使用.png的无损保存格式。

 

1. 基本处理函数

0)

img = cv2.imread(img_path)
height, widtdh, channels = img.shape  # rows, cols
cv2.imwrite(img_path, img_array)    # img_path shouldn't contain 中文

* cv2.imread读入的对象的通道顺序为BGR,图像文件中是有标注通道的,所以知道哪个是R、G、B通道,cv2读入是进行转换为BGR即可。

* cv2.imwrite则是将当前 array 的三个通道分别视为B、G、R通道,保存。array中只是数据,并不能标记r、g、b通达,需要代码处理好。

  参考博客中 “读取bgr格式图片为bgr格式读入;读取rgb格式图片为rgb格式读入” 错误,应该是src.jpg是正确读入了(进行了BGR转换),而src_rgb.jpg中的R、G、B在保存时分别被视为B、G、R通道,再用cv2读入时无需转换通道,即读入后array中的通道B、G、R分别对应src.jpg中的R、G、B,所以图片展示效果不一样。

* 若图片路径中包含中文,不便修改,可以用如下方法读写:  ——参考博客

import cv2
import numpy as np

file_path = '中文.jpg'
img = cv2.imdecode(np.fromfile(file_path, dtype=np.uint8), -1) # read
cv2.imencode('.jpg', img )[1].tofile(file_path)                # write

 

 

1)cv2.waitKey(t)  #等待t ms后继续执行,t=0则无限等待,返回值为键盘输入的键值的ASCII值

...
input = cv2.waitKey(0)   # input is ASCII value of key
...
cv2.waitKey(0)       # will not stop waitting
...

2)灰度转换

img = cv2.imread('xx.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) img_rgb = cv2.cvtColor(gray, cv2.COLOR_GRAY2BGR)

* 问题:灰度图抓BGR三通道彩色图时遇到问题:VScn::contains(scn) && VDcn::contains(dcn) && VDepth::contains(depth) in function 'cv::CvtHelper<struct cv::Set<1,-1,-1>,struct cv::Set<3,4,-1>,struct cv::Set<0,2,5>,2>::CvtHelper'

具体来讲是图像的深度不受支持,根据GitHub上的回答,opencv只将[0, 1]范围内的值视为float类型,而前面BGR2GRAY后,灰度图的范围是[0, 255],会被视为整数,但它要处理float类型的,解决办法为转换为uint8类型:

img = img.astype('uint8')

 

3)二值化/阈值化  ——功能解析参考opencvopencv解析

ret,thresh = cv2.threshold(img,127,255,cv2.THRESH_BINARY)  # (img, threshold, max_value, mode)

 4) resize

img = cv2.resize(img, (400, 500))    # (img, (width, height))

 

* 将图像转换为目标大小的一种方法 (h, w ——> height, width)

  先通过加黑边的方式把图像的纵横比调整为目标大小的纵横比,再resize到目标大小,可以保持图像内容不变形。非精准变换,可能会有轻微的形变。

def resize(input_img, height, width):
    h, w, _ = input_img.shape
    t, b, l, r = 0, 0, 0, 0
    if h/w < height/width:              # it's short in h
        add = w*height/width - h
        t = add//2
        b = add-t
    else:                               # it's short in w
        add = h*width/height - w
        l = add//2
        r = add-l
    # add boder to keep the same ratio of w and h with target (width and height)
    input_img = cv2.copyMakeBorder(input_img, int(t), int(b), int(l), int(r), cv2.BORDER_CONSTANT)  # add black boder
    return cv2.resize(input_img, (width, height))

 

 

5)图像边界扩展  ——增强结果参考博客

a = cv2.copyMakeBorder(img,50,50,50,50, cv2.BORDER_REPLICATE)          # 将原边界上的像素向外平行复制50个像素的距离,相当于边界上像素的拉伸,形如:A.....
a = cv2.copyMakeBorder(img,50,50,50,50, cv2.BORDER_REFLECT)            # 以原边界为轴,分别将四条边内的50个像素内的内容翻折出去,形如: q|p
a = cv2.copyMakeBorder(img,50,50,50,50, cv2.BORDER_CONSTANT,value=[0,255,0]) # 在四条边外个添加50个像素宽的内容,添加的为值为value的像素

 6)翻转与旋转

  def flip(src, flipCode, dst=None),flipCode: 0- > 上下翻转,大于0 -> 左右翻转,小于0 -> 上下+左右翻转

i_flip = cv2.flip(img, 0)

 

  def rotate(src, rotateCode, dst=None),顺时针旋转,rotateCode有90°,180°,270°三种可选

lp1 = cv2.rotate(img, cv2.ROTATE_90_CLOCKWISE)          # 90
lp2 = cv2.rotate(img, cv2.ROTATE_90_COUNTERCLOCKWISE)    # 270(即-90)
lp3 = cv2.rotate(img, cv2.ROTATE_180)              # 180

 

2. opencv读取的图片不管是视频帧还是图片都是矩阵形式,即np.array,要转PIL.Image格式用PIL.Image.fromarray()函数,参见:cv2和PIL图片的颜色通道

3.以下是opencv-python可以获取视频的相关信息,可以通过从0开始的序号获取

0 CV_CAP_PROP_POS_MSEC     视频文件的当前位置(以毫秒为单位)或视频捕获时间戳。
1 CV_CAP_PROP_POS_FRAMES      接下来要解码/捕获的帧的基于0的索引
2 CV_CAP_PROP_POS_AVI_RATIO   视频文件的相对位置:0 - 电影的开始,1 - 电影的结尾。
3 CV_CAP_PROP_FRAME_WIDTH    视频流中帧的宽度
4 CV_CAP_PROP_FRAME_HEIGHT  视频流中帧的高度
5 CV_CAP_PROP_FPS          帧速率
6 CV_CAP_PROP_FOURCC       编解码器的4字符代码
7 CV_CAP_PROP_FRAME_COUNT        视频文件中的帧数
8 CV_CAP_PROP_FORMAT        返回的Mat对象的格式 retrieve() 
9 CV_CAP_PROP_MODE       指示当前捕获模式的特定于后端的值
10 CV_CAP_PROP_BRIGHTNESS   图像的亮度(仅适用于相机)
11 CV_CAP_PROP_CONTRAST    图像对比度(仅适用于相机)
12 CV_CAP_PROP_SATURATION    图像的饱和度(仅适用于相机)
13 CV_CAP_PROP_HUE         图像的色调(仅适用于相机)
14 CV_CAP_PROP_GAIN        图像的增益(仅适用于相机)
15 CV_CAP_PROP_EXPOSURE     曝光(仅适用于相机)
16 CV_CAP_PROP_CONVERT_RGB   布尔标志,指示是否应将图像转换为RGB
17 CV_CAP_PROP_WHITE_BALANCE_U 白平衡设置的U值(注意:目前仅支持DC1394 v 2.x后端)
18 CV_CAP_PROP_WHITE_BALANCE_V 白平衡设置的V值(注意:目前仅支持DC1394 v 2.x后端)
19 CV_CAP_PROP_RECTIFICATION   立体摄像机的整流标志(注意:目前仅支持DC1394 v 2.x后端)
20 CV_CAP_PROP_ISO_SPEED     摄像机 的ISO速度(注意:目前仅支持DC1394 v 2.x后端)
21 CV_CAP_PROP_BUFFERSIZE     存储在内部缓冲存储器中的帧数(注意:目前仅支持DC1394 v 2.x后端)

如视频时长 = cap.get(7)/cap.get(5),单位为s
原文链接

4. 有的函数处理后,像素值范围在0-1,直接用cv2保存会以0-255的范围进行map,显得一片黑,可以用normalize——参考博客

img = cv2.normalize(img, img, 0, 255, cv2.NORM_MINMAX)
img = cv2.convertScaleAbs(img)

 

5. 经典的图像处理功能函数

1)滤波函数  ——参考博客

import cv2

img = cv2.imread('cat.jpg')
 
img_mean = cv2.blur(img, (5, 5))              # 均值滤波,滤波核为(5,5) 
img_Guassian = cv2.GaussianBlur(img,(5,5),0)    # 高斯滤波 
img_median = cv2.medianBlur(img, 5)         # 中值滤波 
img_bilater = cv2.bilateralFilter(img,9,75,75)    # 双边滤波

2)膨胀与腐蚀

kernel = np.ones((5, 5), np.uint8)          # 设置卷积核5*5
erosion = cv2.erode(src, kernel)            # 腐蚀,默认迭代次数
dst = cv2.dilate(erosion, kernel)           # 膨胀

3)开操作与闭操作等  ——参考博客博客2

开操作 = 腐蚀 + 膨胀,断开小间隔,消除突出物,使轮廓更光滑

闭操作 = 膨胀 + 腐蚀,填充小间隔,小空洞,断裂线,使轮廓更光滑

iopen = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)        # 开
iclose = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel)      # 闭
top_hat = cv2.morphologyEx(img, cv2.MORPH_TOPHAT, kernel)      # 顶帽,突出图像中比周围亮的部分
black_hat = cv2.morphologyEx(img, cv2.MORPH_BLACKHAT, kernel)  # 黑帽,突出图像中比周围暗的部分
gradient = cv2.morphologyEx(img, cv2.MORPH_GRADENT, kernel)    # 形态学梯度

* 基本梯度:形态学梯度,dst-erosion,拟合边界;  内部梯度:img-erosion,拟合内轮廓;  外部梯度:dst-img,拟合外轮廓。

4)边缘算子

# sobel
horizontal = cv2.Sobel(gray,0, 1,0, cv2.CV_64F)    # 垂直边缘
vertical = cv2.Sobel(gray,0, 0,1, cv2.CV_64F)     # 水平边缘
# laplacian
lappy = cv2.Laplacian(gray, cv2.CV_64F)    #
# canny
canny=cv2.Canny(gray, 40, 140)              # Canny算子的上下灰度阈值分别取140,40

 

 

4. 视频处理 ——   另一篇博文

posted @ 2020-06-25 11:31  谷小雨  阅读(402)  评论(0编辑  收藏  举报