OpenCV第四弹

不同色彩空间的转换:

常用的色彩空间:

①灰度:去除彩色信息获得灰阶,对中间处理有效,如人脸检测。

②BGR:蓝-绿-红,每一个像素点都由一个三元组表示。

③HSV:色调(Hue)-饱和度(Saturation)-明度(Value)。

傅里叶变化:Joseph Fourier

高通滤波器(HPF):检测图像的某个区域,然后根据像素与周围像素的亮度差值来提升该像素的亮度的滤波器。(边缘检测)

直白点说,就是中央像素如果与周围的亮度差值很大,中央像素的亮度增加。

import cv2
import numpy as np
from scipy import ndimage

kernel_3x3 = np.array(
    [[-1, -1, -1],
     [-1, 8, -1],
     [-1, -1, -1]]
)

kernel_5x5 = np.array(
    [[-1, -1, -1, -1, -1],
     [-1, 1, 2, 1, -1],
     [-1, 2, 4, 2, -1],
     [-1, 1, 2, 1, -1],
     [-1, -1, -1, -1, -1]]
)
# 滤波器中的所有值加起来为0

img = cv2.imread('Cat.jpg', 0)
k3 = ndimage.convolve(img, kernel_3x3)
k5 = ndimage.convolve(img, kernel_5x5)

blurred = cv2.GaussianBlur(img, (11,11), 0)
g_hpf = img - blurred
cv2.imshow("3x3", k3)
cv2.imshow("5x5", k5)
cv2.imshow("g_hpf", g_hpf)
cv2.waitKey()
cv2.destroyAllWindows()

 处理效果:

低通滤波器(LPF):在像素与周围像素的亮度差值小于某一特定值时,平滑该像素的亮度。(去噪、模糊化)

边缘检测:

先对图像进行模糊处理,避免将噪声误认为边缘。blur()\medianBlur()\GaussianBlur()

img = cv2.imread('Cat.jpg')
blurKsize = 7
edgeKsize = 5
dst = 3
if blurKsize >= 3:
    blurredImg = cv2.medianBlur(img, blurKsize)
    grayImg = cv2.cvtColor(blurredImg, cv2.COLOR_BGR2GRAY)
else:
    grayImg = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
cv2.Laplacian(grayImg, cv2.CV_8U, grayImg, ksize=edgeKsize)
normalizedInverseAlpha = (1.0 / 255) * (255 - grayImg)
channels = cv2.split(img)
for channel in channels:
    channel[:] = channel * normalizedInverseAlpha
cv2.merge(channels, dst)
cv2.imshow('jbkj', channels)

Canny边缘检测

步骤:

①使用高斯滤波器对图像进行去噪;

②计算梯度;

③在边缘上使用非最大抑制(NMS);

④在边缘上使用双阈值去除假阳性;

⑤分析所有的边缘及其之间的连接,保留真正的边缘并消除不明显的边缘。

img = cv2.imread('Cat.jpg', 0)
canny_img = cv2.Canny(img, 200, 300)
cv2.imshow('canny', canny_img)
cv2.waitKey()
cv2.destroyAllWindows()

轮廓检测

threshold函数,可用于二值化处理,设置阈值,选择不同的像素筛选策略。

# 200x200黑色图像
img = np.zeros((200, 200), dtype=np.uint8)
# 正中央白色正方形,切片
img[50:150, 50:150] = 255
# 当阈值大于127时,像素点设置为255;小于127时,设置为0;cv2.THRESH_BINARY
ret, thresh = cv2.threshold(img, 127, 255, 0)
# 输入图像、层次类型、轮廓逼近方式 
"""
cv2.RETR_EXTERNAL表示只检测外轮廓
cv2.RETR_LIST检测的轮廓不建立等级关系
cv2.RETR_CCOMP建立两个等级的轮廓,上面的一层为外边界,里面的一层为内孔的边界信息。
cv2.RETR_TREE建立一个等级树结构的轮廓。


cv2.CHAIN_APPROX_NONE存储所有的轮廓点
cv2.CHAIN_APPROX_SIMPLE压缩水平方向,垂直方向,对角线方向的元素,只保留该方向的终点坐标
"""

contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
color = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
img = cv2.drawContours(color, contours, -1, (0, 255, 0), 2)
cv2.imshow("contours", color)
cv2.waitKey()
cv2.destroyAllWindows()

处理结果: 

# 读入图像
image = cv2.imread("yoghurt.jpg")
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 当阈值大于127时,像素点设置为255;小于127时,设置为0;cv2.THRESH_BINARY
ret, thresh = cv2.threshold(gray, 127, 255, 0)
# 输入图像、层次类型、轮廓逼近方式
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
# color = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
img = cv2.drawContours(image, contours, -1, (0, 0, 255), 2)
cv2.imshow("contours", image)
cv2.waitKey()
cv2.destroyAllWindows()

最小外接矩形/圆 

现实应用涉及对目标边界框、最小矩形面积、最小外接圆的需求。

矩形边框(Bounding Rectangle)是说,用一个最小的矩形,把找到的形状包起来。还有一个带旋转的矩形,面积会更小

img = cv2.pyrDown(cv2.imread("hammer.jpg", cv2.IMREAD_UNCHANGED))
# pyrDown下采样;unchanged读入完整图片,包括alpha通道
ret, thresh = cv2.threshold(cv2.cvtColor(img.copy(), cv2.COLOR_BGR2GRAY), 127, 255, cv2.THRESH_BINARY)
# 二值化处理
contours, h = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# 最外轮廓
for c in contours:
    # 计算边界框,得到左上角坐标及长宽
    x, y, w, h = cv2.boundingRect(c)
    # 画矩形
    cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2)
    # 计算包围目标的最小区域
    rect = cv2.minAreaRect(c)
    box = cv2.boxPoints(rect)
    box = np.int32(box)
    cv2.drawContours(img, [box], 0, (0, 0, 255), 3)
    (x, y), radius = cv2.minEnclosingCircle(c)
    center = (int(x), int(y))
    radius = int(radius)
    img = cv2.circle(img, center, radius, (0, 255, 0), 2)
# -1绘制所有的轮廓
cv2.drawContours(img, contours, -1, (255, 0, 0), 1)
cv2.imshow("cnt", img)
cv2.waitKey()
cv2.destroyAllWindows()

处理结果:

凸轮廓与Douglas-Peucker算法

凸形状内部的任意两点的连线都在形状内部。

# 轮廓的多边形拟合
img = cv2.imread("ploy.jpg", flags=1)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  # 灰度图像
blur = cv2.boxFilter(gray, -1, (5, 5))  # 盒式滤波器,5*5 平滑核
_, binary = cv2.threshold(blur, 205, 255, cv2.THRESH_OTSU + cv2.THRESH_BINARY)

# 寻找二值化图中的轮廓
contours, hierarchy = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
print('len:', len(contours))

# 绘制轮廓函数会修改原始图像
imgCnts = np.zeros(gray.shape[:2], np.uint8)  
# 绘制全部轮廓
imgCnts = cv2.drawContours(imgCnts, contours, -1, (255, 255, 255), thickness=2)  

plt.figure(figsize=(9, 6))
plt.subplot(231), plt.axis('off'), plt.title("Origin")
plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
plt.subplot(232), plt.axis('off'), plt.title("Binary")
plt.imshow(binary, 'gray')
plt.subplot(233), plt.axis('off'), plt.title("Contour")
plt.imshow(imgCnts, 'gray')
# 所有轮廓按面积排序
cnts = sorted(contours, key=cv2.contourArea, reverse=True)  
cnt = cnts[0]  # 第 0 个轮廓,面积最大的轮廓
print("shape of max contour:", cnt.shape[0])

eps = [50, 30, 10]
for i in range(len(eps)):
    polyFit = cv2.approxPolyDP(cnt, eps[i], True)
    print("eps={}, shape of fitting polygon:{}".format(eps[i], polyFit.shape[0]))
    fitContour = np.zeros(gray.shape[:2], np.uint8)  # 初始化最大轮廓图像
    cv2.polylines(fitContour, [cnt], True, 205, thickness=2)  # 绘制最大轮廓,多边形曲线
    cv2.polylines(fitContour, [polyFit], True, 255, 3)
    plt.subplot(2, 3, i + 4), plt.axis('off'), plt.title("approxPoly(eps={})".format(eps[i]))
    plt.imshow(fitContour, 'gray')

plt.tight_layout()
plt.show()

 盒式滤波器:

直线检测:

HoughLines(标准Hough变换)和HoughLinesP(概率Hough变换)函数。

img = cv2.imread("lines.jpg")
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray, 50, 120)
minLineLength = 20
maxLineGap = 5
lines = cv2.HoughLinesP(edges, 1, np.pi / 180, 100, minLineLength, maxLineGap)
for x1, y1, x2, y2 in lines[0]:
    cv2.line(img, (x1, y1), (x2, y2), (0, 255, 0), 2)
cv2.imshow("edges", edges)
cv2.imshow("lines", img)
cv2.waitKey()
cv2.destroyAllWindows()

圆的检测

planets = cv2.imread('circle.jpg')
gray = cv2.cvtColor(planets, cv2.COLOR_BGR2GRAY)
img = cv2.medianBlur(gray, 5)
cimg = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
circles = cv2.HoughCircles(img, cv2.HOUGH_GRADIENT, 1, 120, param1=100, param2=30, minRadius=0, maxRadius=0)
# 灰度图像,基于梯度,累加器分辨率,阈值,圆心精度,检测到的圆的最小半径,最小半径,最大半径。
circles = np.uint16(np.around(circles))
for i in circles[0, :]:
    cv2.circle(planets, (i[0], i[1]), i[2], (0, 0, 0), 2)
    cv2.circle(planets, (i[0], i[1]), 2, (0, 255, 0), 3)
cv2.imwrite("planet_circles.jpg", planets)
cv2.imshow('HoughCircles', planets)
cv2.waitKey()
cv2.destroyAllWindows()

thickness=1

thickness=3

thickness=5

 二值化总结:OpenCV-二值化方法-CSDN博客

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值