计算机系统应用教程网站

网站首页 > 技术文章 正文

Python-OpenCV 10. 图像边缘算法 opencv边缘识别

btikc 2024-10-12 10:22:21 技术文章 13 ℃ 0 评论

一、介绍

边缘检测是图像处理和计算机视觉中的基本问题,边缘检测的目的是标识数字图像中亮度变化明显的点。图像属性中的显著变化通常反映了属性的重要事件和变化。

二、几种边缘检测算法

1. 欧氏距离算法

将当前像素与邻接的下部和右部的像素进行比较,如果相似,则将当前像素设置为白色,否则设置为黑色。

判定像素是否相似,使用欧氏距离算法,将一个像素的三个色彩分量映射在三维空间中,如果2个像素点的欧氏距离小于某个常数的阈值,就认为它们相似。

# -*- coding: utf-8 -*-
import cv2
import numpy as np
import matplotlib.pyplot as plt
fn = 'test.jpg'
def get_EuclideanDistance(x, y):
 myx = np.array(x)
 myy = np.array(y)
 return np.sqrt(np.sum((myx - myy) * (myx - myy)))
if __name__ == '__main__':
 print('loading %s ...' % fn)
 print('working', )
 myimg1 = cv2.imread(fn)
 w = myimg1.shape[1]
 h = myimg1.shape[0]
 sz1 = w
 sz0 = h
 # 创建空白图像
 myimg2 = np.zeros((sz0, sz1, 3), np.uint8)
 # 对比产生线条
 black = np.array([0, 0, 0])
 white = np.array([255, 255, 255])
 centercolor = np.array([125, 125, 125])
 for y in range(0, sz0 - 1):
 for x in range(0, sz1 - 1):
 mydown = myimg1[y + 1, x, :]
 myright = myimg1[y, x + 1, :]
 myhere = myimg1[y, x, :]
 lmyhere = myhere
 lmyright = myright
 lmydown = mydown
 if get_EuclideanDistance(lmyhere, lmydown) > 16 and get_EuclideanDistance(lmyhere, lmyright) > 16:
 myimg2[y, x, :] = black
 elif get_EuclideanDistance(lmyhere, lmydown) <= 16 and get_EuclideanDistance(lmyhere, lmyright) <= 16:
 myimg2[y, x, :] = white
 else:
 myimg1[y, x, :] = centercolor
 print('.', )
 plt.subplot(1, 2, 1), plt.title('original')
 plt.imshow(myimg1)
 plt.subplot(1, 2, 2), plt.title('gaussian')
 plt.imshow(myimg2)
 plt.show()

2. Laplacian

Laplacian 算子是n维欧几里德空间中的一个二阶微分算子,定义为梯度grad的散度div。可使用运算模板来运算这定理定律。

Laplacian 算子对噪声比较敏感,所以图像一般先经过平滑处理,因为平滑处理也是用模板进行的,所以,通常的分割算法都是把Laplacian 算子和平滑算子结合起来生成一个新的模板。

OpenCV2的Lapacian算法函数:

cv2.Laplacian(src,ddepth[, dst[, ksize[, scale[, delta[, borderType]]]]]) -> dst

代码

# -*- coding: utf-8 -*-
# coding=utf-8
import cv2
fn = "test.jpg"
myimg = cv2.imread(fn)
img = cv2.cvtColor(myimg, cv2.COLOR_BGR2GRAY)
img_small = cv2.resize(img, (500, 300), interpolation=cv2.INTER_CUBIC)
jpimg = cv2.Laplacian(img_small, -1)
cv2.imshow('src', img_small)
cv2.imshow('dst', jpimg)
cv2.waitKey()
cv2.destroyAllWindows()

3. sobel 非线性滤波

sobel非线性滤波采用梯度模的近似方式提取边缘,锐化图像,可以分别计算水平和垂直方向上的灰阶突变。

# -*- coding: utf-8 -*-
# coding=utf-8
# 线性锐化滤波,拉普拉斯图像变换
import cv2
import numpy as np 
fn = "test.jpg"
myimg = cv2.imread(fn)
img=cv2.cvtColor(myimg,cv2.COLOR_BGR2GRAY)
img_small=cv2.resize(img,(500,300),interpolation=cv2.INTER_CUBIC)
jpimg = cv2.Sobel(img_small, 0, 1, 1,)
cv2.imshow('src',img_small)
cv2.imshow('dst',jpimg)
cv2.waitKey()
cv2.destroyAllWindows()
import cv2
from matplotlib import pyplot as plt
img = cv2.imread("test.jpg", 0)
# 读取图像,0为灰度图像,1为彩色图像
x = cv2.Sobel(img, cv2.CV_16S, 1, 0)
y = cv2.Sobel(img, cv2.CV_16S, 0, 1)
absX = cv2.convertScaleAbs(x)
absY = cv2.convertScaleAbs(y) # 转回uint8
dst = cv2.addWeighted(absX, 0.5, absY, 0.5, 0)
plt.subplot(221), plt.imshow(img, 'gray')
plt.subplot(222), plt.imshow(absX, 'gray')
plt.subplot(223), plt.imshow(absY, 'gray')
plt.subplot(224), plt.imshow(dst, 'gray')
plt.show()

4. Canny边缘检测

Canny边缘检测可以相对有效的连接断裂的边缘,需要指定一个最大最小灰阶值组成区间,结果生成的是二值图像。

cv2.Canny(image, threshold1, threshold2[, edges[, apertureSize[, L2gradient]]])

mage:输入图像

threshold1和threshold2:minVal和maxVal

apertureSize:用于查找图像渐变的Sobel内核的大小,3(默认)

L2gradient:指定用于查找梯度幅度的等式,如果它是True,它使用上面提到的更准确的等式,否则它=False(默认)使用:

Edge_Gradient(G)=|Gx|+|Gy|

import cv2
from matplotlib import pyplot as plt
img = cv2.imread('test.jpg', 0)
edges = cv2.Canny(img, 100, 200)
plt.subplot(121), plt.imshow(img, cmap='gray')
plt.title('Original Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122), plt.imshow(edges, cmap='gray')
plt.title('Edge Image'), plt.xticks([]), plt.yticks([])
plt.show()

三、OpenCV 轮廓检测函数

1. findContours drawContours

OpenCV-Python接口中使用cv2.findContours()函数来查找检测物体的轮廓。

import cv2
img = cv2.imread('test.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
contours, hierarchy = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(img, contours, -1, (0, 0, 255), 3)
cv2.imshow("img", img)
cv2.waitKey(0)

需要注意的是cv2.findContours()函数接受的参数为二值图,即黑白的(不是灰度图),所以读取的图像要先转成灰度的,再转成二值图。

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表