前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >OpenCV与图像处理(二)

OpenCV与图像处理(二)

作者头像
Must
发布2020-07-28 11:43:50
5830
发布2020-07-28 11:43:50
举报
文章被收录于专栏:机器视觉工坊机器视觉工坊

本章节的主要内容是图像分割,包括以下几点内容:

1、阈值二值化

2、Canny算子

3、Sobel算子

4、Laplace算子

以下代码均在python3.6,opencv4.2.0环境下试了跑一遍,可直接运行。


1、阈值二值化

阈值二值化,就是将图像上的像素点的灰度值设置为0或255,也就是将整个图像呈现出明显的只有黑和白的视觉效果。灰度值0:黑,灰度值255:白。

阈值分割方法的核心在于如何寻找适当的阈值。最常用的阈值方法是基于灰度直方图的方法,如最大类间方差法(OTSU)、最小误差法、最大熵法等,直方图表示图像中具有每种灰度级的像素的个数。直方图方法选择二值化阈值主要是发现图像的两个最高的峰,然后在阈值取值在两个峰之间的峰谷最低处。

1)完整代码如下:

代码语言:javascript
复制
# -*- coding: utf-8 -*-

import cv2
import numpy as np

img_path = "test.jpg"
img=cv2.imread(img_path)
gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)

# 高斯去燥
gaussianBlur_img = cv2.GaussianBlur(gray, (5, 5), 0)

# 阈值二值化分割
ret, threshold_binary = cv2.threshold(gaussianBlur_img, 155, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)

#寻找轮廓
h = cv2.findContours(threshold_binary,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
# 也可以直接用contours表示
# binary, contours, hierarchy = cv2.findContours(threshold_binary,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)

#提取轮廓
contours = h[0]
#打印返回值,这是一个元组
print(type(h))
#打印轮廓类型,这是个列表
print(type(h[1]))
#查看轮廓数量
print (len(contours))

# 在二值图像上画出轮廓:threshold_binary是二值图像,contours是轮廓,-1表示全画,然后是颜色,厚度
cv2.drawContours(img,contours,-1,(0,255,0),3)
cv2.imshow("threshold_binary_image", img)

# 创建白色幕布
temp = np.ones(threshold_binary.shape,np.uint8)*255
# 在白色幕布上画出轮廓:temp是白色幕布,contours是轮廓,-1表示全画,然后是颜色,厚度
cv2.drawContours(temp,contours,-1,(0,255,0),3)
cv2.imshow("temp_threshold_binary_image",temp)

cv2.waitKey(0)
cv2.destroyAllWindows()

2)运行结果如下:

原图上的二值分割结果

白色幕布上的二值分割结果

2、Canny算子

canny边缘检测的基本思想是:首先对图像选择一定的Gauss滤波器进行平滑滤波,然后采用非极值抑制技术进行处理得到最后的边缘图像。Canny算子力图在抗噪声干扰和精确定位之间寻求最佳折中方案。

Canny算子求边缘的具体算法步骤如下:

1. 用高斯滤波器平滑图像.

2. 用一阶偏导有限差分计算梯度幅值和方向.

3. 对梯度幅值进行非极大值抑制.

4. 用双阈值算法检测和连接边缘.

1)完整代码如下:

代码语言:javascript
复制
# -*- coding: utf-8 -*-

import cv2
import numpy as np

img_path = "test.jpg"
img=cv2.imread(img_path)
gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)

# 高斯去燥
gaussianBlur_img = cv2.GaussianBlur(gray, (5, 5), 0)

# canny检测
cannyImg = cv2.Canny(gaussianBlur_img,50,200)

#寻找轮廓
h = cv2.findContours(cannyImg,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)

#提取轮廓
contours = h[0]
#打印返回值,这是一个元组
print(type(h))
#打印轮廓类型,这是个列表
print(type(h[1]))
#查看轮廓数量
print (len(contours))

# 在二值图像上画出轮廓:threshold_binary是二值图像,contours是轮廓,-1表示全画,然后是颜色,厚度
cv2.drawContours(img,contours,-1,(0,255,0),3)
cv2.imshow("cannyImg_image", img)

# 创建白色幕布
temp = np.ones(cannyImg.shape,np.uint8)*255
# 在白色幕布上画出轮廓:temp是白色幕布,contours是轮廓,-1表示全画,然后是颜色,厚度
cv2.drawContours(temp,contours,-1,(0,255,0),3)
cv2.imshow("temp_cannyImg_image",temp)

cv2.waitKey(0)
cv2.destroyAllWindows()

2)运行结果如下:

原图上的canny分割结果

白色幕布上的canny分割结果

3、Sobel算子

Sobel算子根据像素点上下、左右邻点灰度加权差,在边缘处达到极值这一现象检测边缘。对噪声具有平滑作用,提供较为精确的边缘方向信息,边缘定位精度不够高。当对精度要求不是很高时,是一种较为常用的边缘检测方法。

1)完整代码如下:

代码语言:javascript
复制
# -*- coding: utf-8 -*-

import cv2
import numpy as np

img_path = "test.jpg"
img=cv2.imread(img_path)
gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)

# Sobel检测:普通一阶差分,基于寻找梯度强度,边缘提取
# ddepth =-1/CV_16S/CV_32F/CV_64F 
# sobel 水平方向边缘检测
x = cv2.Sobel(gray,cv2.CV_16S,1,0,ksize=3)
# 将像素点进行绝对值计算
sobelx_img = cv2.convertScaleAbs(x)

# sobel 竖直方向边缘检测
y = cv2.Sobel(gray,cv2.CV_16S,0,1,ksize=3)
# 将像素点进行绝对值计算
sobely_img = cv2.convertScaleAbs(y)

# sobel边缘检测,两个方向图像加权混合,融合,addWeighted()也可以设置图片的透明度
sobelxy_img = cv2.addWeighted(sobelx_img, 0.5, sobely_img, 0.5, 0)

# sobel边缘检测,两个方向同时进行检测
sobel_edges = cv2.Sobel(img,cv2.CV_16S,1,1,ksize=3) 
# 将像素点进行绝对值计算
sobel_img = cv2.convertScaleAbs(sobel_edges)

cv2.imshow("sobelx_img", sobelx_img)
cv2.imshow("sobely_img", sobely_img)
cv2.imshow("sobelxy_img", sobelxy_img)
cv2.imshow("sobel_img", sobel_img)

cv2.waitKey(0)
cv2.destroyAllWindows()

2)运行结果如下:

sobel 水平方向检测结果

sobel 竖直方向检测结果

sobel 水平竖直两个方向加权混合检测结果

sobel 水平竖直同时检测结果

4、Laplace算子

laplace算子是最简单的各向同性微分算子,它具有旋转不变性。一个二维图像函数的拉普拉斯变换是各向同性的二阶导数。在一阶导数的极值位置,二阶导数为0。可以用这个特点来作为检测图像边缘的方法。但是, 二阶导数的0值不仅仅出现在边缘,也可能出现在无意义的位置,可以过滤掉这些点。

1)完整代码如下:

代码语言:javascript
复制
# -*- coding: utf-8 -*-

import cv2
import numpy as np

img_path = "test.jpg"
img=cv2.imread(img_path)
gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)

# Laplace检测:无高斯滤波
laplace_img = cv2.Laplacian(gray, cv2.CV_16S, ksize = 3)
# 将像素点进行绝对值计算
laplace_img = cv2.convertScaleAbs(laplace_img)
cv2.imshow("laplace_image", laplace_img)


# Laplace检测:有高斯滤波
# 高斯去燥
gaussianBlur_img = cv2.GaussianBlur(gray, (5, 5), 0)
# 拉普拉斯检测
laplace_img = cv2.Laplacian(gray, cv2.CV_16S, ksize = 3)
# 将像素点进行绝对值计算
gauss_laplace_img = cv2.convertScaleAbs(laplace_img)
cv2.imshow("gauss_laplace_image", gauss_laplace_img)

cv2.waitKey(0)
cv2.destroyAllWindows()

2)运行结果如下:

无高斯去燥的Laplace算子分割结果

有高斯去燥的Laplace算子分割结果

有无高斯去燥对Laplace算子的分割结果没有影响。

以上内容如有错误或者需要补充的,请留言!

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-06-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 机器视觉工坊 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
图像处理
图像处理基于腾讯云深度学习等人工智能技术,提供综合性的图像优化处理服务,包括图像质量评估、图像清晰度增强、图像智能裁剪等。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档