1. opencv简单图像处理
  2.1 图像像素存储形式
    首先得了解下图像在计算机中存储形式:(为了方便画图,每列像素值都写一样了)
    对于只有黑白颜色的灰度图,为单通道,一个像素块对应矩阵中一个数字,数值为0到255, 其中0表示最暗(黑色) ,255表示最亮(白色)
    opencv - 图1

    对于采用RGB模式的彩色图片,为三通道图,Red、Green、Blue三原色,按不同比例相加,一个像素块对应矩阵中的一个向量, 如[24,180, 50],分别表示三种颜色的比列, 即对应深度上的数字,如下图所示:
    opencv - 图2
    需要注意的是,由于历史遗留问题,opencv采用BGR模式,而不是RGB

2.2 图像读取和写入图片.png
图片.png
2.3 图像像素获取和编辑
图片.png
图片.png
图片.png
 2.4 添加边界(padding) 
图片.png
使用示例
图片.png
图片.png

常用的函数

img=cv2.imread(‘cat.jpg’,cv2.IMREAD_COLO)

图片的读取,cv2.IMREAD_COLO 彩色图片 cv2.IMREAD_GRAYSCALE 灰度图片 ,不填得到的格式是BGR img类型,numpy.ndarray 数据类型,uint8

img.shape 获取图片形状 img.size 获取图片像素点,

cv2.imshow(name,img) cv2.imwrite(‘mycat.png’,img)

图片的显示, 存储图片

cv2.waitKey(0)

显示时间。ms, 0代表任意键退出 1000 代表1秒后退出
key = cv2.waitKey(0) 获取按键输入值 key==27 代表ESC键) 获取按键输入值
在读取视频时可以用来限制每秒读取的帧数
if cv2.waitKey(100) & 0xFF == 27: 键位值与上111 111

cat=img[0:50,0:200] 可以使用numpy的截取处理图片

b,g,r=cv2.split(img) cv2.split(img) 按通道分离

img=cv2.merge((b,g,r)) 按通道合并图像

cur_img = img.copy() 拷贝图像

cap = cv2.VideoCapture(“./data/羊圈溜达模式.mp4”)

读取视频,也可以用数字代表本机的摄像头 cv2.VideoCapture(0)

cap.release() 释放视频资源

cv2.namedWindow(‘Video’) 获取一个显示窗口

cv2.destroyAllWindows() 关闭所有窗口 cv2.destroyWindow()

falg, first_frame = cap.read()

读取视频,转为每帧图像,每次拿一帧,flag获取是否成功,可以用于判断视频是否结束。frame图像

cv2.cvtColor(first_frame, cv2.COLOR_BGR2GRAY)

改变颜色 cv2.COLOR_GRAY2RGB cv2.COLOR_BGR2GRAY cv2.COLOR_BGR2HSV

replicate = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size,

borderType=cv2.BORDER_REPLICATE)

边界填充

  1. - BORDER_REPLICATE:复制法,也就是复制最边缘像素。
  2. - BORDER_REFLECT:反射法,对感兴趣的图像中的像素在两边进行复制例如:fedcba|abcdefgh|hgfedcb
  3. - BORDER_REFLECT_101:反射法,也就是以最边缘像素为轴,对称,gfedcb|abcdefgh|gfedcba
  4. - BORDER_WRAP:外包装法cdefgh|abcdefgh|abcdefg
  5. - BORDER_CONSTANT:常量法,常数值填充。 00255

img_cat2= img_cat +10 img_cat + img_cat2

图像运算,对应位置运算,超过255或取模 %256
cv2.add(img_cat,img_cat2) 超过255会截取

cv2.addWeighted(img_cat, 0.4, img_dog, 0.6, 0)

按比重合并照片

res = cv2.resize(img, (0, 0), fx= 4, fy=4)

缩放图片, x,y扩大4倍 cv2.resize(img_dog, (500, 414)) x,y改为500*414

cv2.threshold(src, thresh, maxval, type) 图片二值化

  1. - src 输入图,只能输入单通道图像,通常来说为灰度图<br />
  2. - dst 输出图<br />
  3. - thresh 阈值<br />
  4. - maxval 当像素值超过了阈值(或者小于阈值,根据type来决定),所赋予的值<br />
  5. - type:二值化操作的类型,包含以下5种类型: cv2.THRESH_BINARY cv2.THRESH_BINARY_INV cv2.THRESH_TRUNC cv2.THRESH_TOZEROcv2.THRESH_TOZERO_INV<br />
  6. - cv2.THRESH_BINARY 超过阈值部分取maxval(最大值),否则取0<br />
  7. - cv2.THRESH_BINARY_INV THRESH_BINARY的反转<br />
  8. - cv2.THRESH_TRUNC 大于阈值部分设为阈值,否则不变<br />
  9. - cv2.THRESH_TOZERO 大于阈值部分不改变,否则设为0<br />
  10. - cv2.THRESH_TOZERO_INV THRESH_TOZERO的反转

threh,ref = cv2.threshold(ref, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU) 自动计算阈值

res = np.hstack((blur,aussian,median)) 图片按行合并

图片平滑

blur = cv2.blur(img, (3, 3)) 均值滤波
cv2.boxFilter(img,-1,(3,3), normalize=True) 方框滤波
cv2.GaussianBlur(img, (5, 5), 1) 高斯滤波 1 代表方差
cv2.medianBlur(img, 5) # 中值滤波 5代表滤波的尺寸

cv2.erode(img,kernel,iterations = 1) 形态学-腐蚀操作(瘦身)

cv2.dilate(dige_erosion,kernel,iterations = 1) 形态学-膨胀操作(增肥)

cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel) 开运算 开:先腐蚀,再膨胀

cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel) 闭:先膨胀,再腐蚀

cv2.morphologyEx(pie, cv2.MORPH_GRADIENT, kernel) 梯度运算 梯度=膨胀-腐蚀

cv2.morphologyEx(img, cv2.MORPH_TOPHAT, kernel) 礼帽 = 原始输入-开运算结果 cv2.morphologyEx(img,cv2.MORPH_BLACKHAT, kernel) 黑帽 = 闭运算-原始输入

kernel = np.ones((3,3),np.uint8)
erosion = cv2.erode(img,kernel,iterations = 1)
dige_dilate = cv2.dilate(dige_erosion,kernel,iterations = 1)
cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)
cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel)
cv2.morphologyEx(pie, cv2.MORPH_GRADIENT, kernel)
1、开运算:先腐蚀后膨胀
开运算可以用来消除小物体,在纤细点分离物体,平滑较大物体的边界的同时不明显的改变其面积。
2、闭运算:先膨胀后腐蚀
闭运算可以排除小的黑色区域。
3、形态学梯度:膨胀与腐蚀图之差
我们可以用形态学梯度来突出边缘,可以保留物体的边缘轮廓。
4、顶帽(Top Hat):原图与开运算结果图之差
开运算放大了裂缝或者局部低亮度的区域,所以,从原图中减去开运算后的图,得到的结果突出了比原图轮廓周围的区域更明亮的区域,这个操作与选择的核的大小有关。TopHat运算一般用来分离比邻近点亮一些的斑块,可以使用这个运算提取背景。
5、黑帽运算(Black Hat):闭运算的结果与原图之差
黑帽运算的结果突出了比原图轮廓周围区域更暗的区域,所以黑帽运算用来分离比邻近点暗一些的斑块。

图像梯度

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

  • ddepth:图像的深度
    - dx和dy分别表示水平和竖直方向
    - ksize是Sobel算子的大小
    sobelx = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=3)
    sobelx = cv2.convertScaleAbs(sobelx) 取绝对值

白到黑是正数,黑到白就是负数了,所有的负数会被截断成0,所以要取绝对值
sobelxy = cv2.addWeighted(sobelx,0.5,sobely,0.5,0) 分别计算x和y,再求和
scharrx = cv2.Scharr(img,cv2.CV_64F,1,0) Scharr算子
scharrx = cv2.Scharr(img,cv2.CV_64F,1,0)
laplacian = cv2.Laplacian(img,cv2.CV_64F) la’p’la’ci’an

laplacian = cv2.convertScaleAbs(laplacian)

图像轮廓

cv2.findContours(img,mode,method)

mode:轮廓检索模式

  • RETR_EXTERNAL :只检索最外面的轮廓;
  • RETR_LIST:检索所有的轮廓,并将其保存到一条链表当中;
  • RETR_CCOMP:检索所有的轮廓,并将他们组织为两层:顶层是各部分的外部边界,第二层是空洞的边界;
  • RETR_TREE:检索所有的轮廓,并重构嵌套轮廓的整个层次;

method:轮廓逼近方法

  • CHAIN_APPROX_NONE:以Freeman链码的方式输出轮廓,所有其他方法输出多边形(顶点的序列)。
  • CHAIN_APPROX_SIMPLE:压缩水平的、垂直的和斜的部分,也就是,函数只保留他们的终点部分。

binary, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
res = cv2.drawContours(draw_img, contours, -1, (0, 0, 255), 2) 绘制轮廓
第一个参数是指明在哪幅图像上绘制轮廓;image为三通道才能显示轮廓
第二个参数是轮廓本身,在Python中是一个list;
第三个参数指定绘制轮廓list中的哪条轮廓,如果是-1,则绘制其中的所有轮廓。
第四个thickness表明轮廓线的宽度,如果是-1(cv2.FILLED),则为填充模式。

cv2.drawContours(image, contours, contourIdx, color, thickness=None,

res = cv2.drawContours(draw_img, [cnt], -1, (0, 0, 255), 2)
cnt = contours[0]
x,y,w,h = cv2.boundingRect(cnt)
img = cv2.rectangle(img,(x,y),(x+w,y+h),(0,255,0),2)
cv2.contourArea(cnt) 轮廓面积

cv2.arcLength(cnt,True) 轮廓周长

epsilon = 0.15*cv2.arcLength(cnt,True)
approx = cv2.approxPolyDP(cnt,epsilon,True) 轮廓近似
img = cv2.rectangle(img,(x,y),(x+w,y+h),(0,255,0),2) 边界矩形

(x,y),radius = cv2.minEnclosingCircle(cnt)
center = (int(x),int(y))
radius = int(radius)
img = cv2.circle(img,center,radius,(0,255,0),2) 边界园

直方图

cv2.calcHist(images,channels,mask,histSize,ranges)

  • images: 原图像图像格式为 uint8 或 float32。当传入函数时应 用中括号 [] 括来例如[img]
  • channels: 同样用中括号括来它会告函数我们统幅图 像的直方图。如果入图像是灰度图它的值就是 [0]如果是彩色图像 的传入的参数可以是 [0][1][2] 它们分别对应着 BGR。
  • mask: 掩模图像。统整幅图像的直方图就把它为 None。但是如 果你想统图像某一分的直方图的你就制作一个掩模图像并 使用它。
  • histSize:BIN 的数目。也应用中括号括来
  • ranges: 像素值范围常为 [0256]

img = cv2.imread(‘cat.jpg’,0) #0表示灰度图
hist = cv2.calcHist([img],[0],None,[256],[0,256])

equ = cv2.equalizeHist(img) 均衡化

cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8)) 自适应的均衡化

res_clahe = clahe.apply(img)

模板匹配

cv2.matchTemplate(img, template, cv2.TM_SQDIFF)

  • TM_SQDIFF:计算平方不同,计算出来的值越小,越相关
  • TM_CCORR:计算相关性,计算出来的值越大,越相关
  • TM_CCOEFF:计算相关系数,计算出来的值越大,越相关
  • TM_SQDIFF_NORMED:计算归一化平方不同,计算出来的值越接近0,越相关
  • TM_CCORR_NORMED:计算归一化相关性,计算出来的值越接近1,越相关
  • TM_CCOEFF_NORMED:计算归一化相关系数,计算出来的值越接近1,越相关

res = cv2.matchTemplate(img, template, cv2.TM_SQDIFF)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)
匹配多个对象
h, w = template.shape[:2]
res = cv2.matchTemplate(img_gray, template, cv2.TM_CCOEFF_NORMED)
threshold = 0.8
# 取匹配程度大于%80的坐标
loc = np.where(res >= threshold)
for pt in zip(loc[::-1]): # 号表示可选参数
bottom_right = (pt[0] + w, pt[1] + h)
cv2.rectangle(img_rgb, pt, bottom_right, (0, 0, 255), 2)
cv2.rectangle(image**, (gX - 5, gY - 5), (gX + gW + 5, gY + gH + 5), (0, 0, 255), 1**) #画矩形,对角点
**

cv2.putText(image, “”.join(groupOutput), (gX, gY - 15), cv2.FONT_HERSHEY_SIMPLEX, 0.65, (0, 0, 255), 2) 图片中画文字

图片.png