求问如何提取图片中的白色区域的轮廓?
这是用红外相机拍摄的火焰图片,图中红圈区域是相机出现了问题产生的噪声。
我用canny算法提取边界的时候噪声会产生影响,而且边界不连续
机械领域研一小白,不知各位有没有方法能够去除噪声的影响,提取出白色区域的轮廓?
十分感谢!
以下答案由GPT-3.5大模型与博主波罗歌共同编写:
您可以尝试以下几种方法:
a. 二值化处理:将图像转换为二值图像,使白色区域为255,黑色区域为0。可以使用阈值分割等方法进行处理。
b. 膨胀操作:使用一个结构元素对二值图像进行膨胀,可以填充白色区域中的空洞,使其更加连续。
c. 腐蚀操作:使用一个结构元素对二值图像进行腐蚀,可以消除白色区域中的噪声点,使其更加连续。
d. 边界提取:使用膨胀后的图像减去腐蚀后的图像,可以得到白色区域的边界。
下面是 Python 中使用 OpenCV 库实现形态学操作的代码:
import cv2
import numpy as np
# 读取图像
img = cv2.imread('fire.jpg', cv2.IMREAD_GRAYSCALE)
# 二值化处理
ret, binary = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)
# 定义结构元素
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3,3))
# 膨胀操作
dilated = cv2.dilate(binary, kernel)
cv2.imshow('dilated', dilated)
# 腐蚀操作
eroded = cv2.erode(binary, kernel)
cv2.imshow('eroded', eroded)
# 边界提取
boundaries = dilated - eroded
cv2.imshow('boundaries', boundaries)
cv2.waitKey(0)
a. 边缘检测:使用 Canny 算法等方法进行边缘检测,得到图像中所有的边缘。
b. 霍夫变换:使用霍夫变换,可以将边缘检测得到的直线转换为参数方程,这样就可以方便地对直线进行处理。
c. 直线筛选:根据直线的参数方程,可以筛选出与噪声区域相交的直线,然后把这些直线合并为一个区域。
d. 轮廓提取:对这个区域进行轮廓提取,就可以得到目标区域的轮廓。
下面是 Python 中使用 OpenCV 库实现霍夫变换的代码:
import cv2
import numpy as np
# 读取图像
img = cv2.imread('fire.jpg', cv2.IMREAD_GRAYSCALE)
# 边缘检测
edges = cv2.Canny(img, 100, 200)
# 霍夫变换
lines = cv2.HoughLinesP(edges, rho=1, theta=np.pi/180, threshold=100, minLineLength=50, maxLineGap=10)
# 直线筛选
region = np.zeros_like(img)
for line in lines:
x1, y1, x2, y2 = line[0]
if 450 < x1 < 600 and 450 < x2 < 600 and 200 < y1 < 400 and 200 < y2 < 400:
cv2.line(region, (x1, y1), (x2, y2), 255, 3)
# 轮廓提取
contours, hierarchy = cv2.findContours(region, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(img, contours, -1, (255, 255, 255), 3)
cv2.imshow('result', img)
cv2.waitKey(0)
注意:
对于两种方法,两种方法只能得到白色区域的轮廓,得到的图像可能不会和原图完全重合。
针对第一种方法,结构元素的大小和形状会影响到结果,需要根据实际情况进行调整。
需要花费一定的时间来调整参数和代码,才能得到最终的结果。
如果我的回答解决了您的问题,请采纳!
如果对您有帮助,希望您能够进行采纳!祝您工作顺利,学业有成!!!
1、可以先膨胀运算,(闭运算去掉黑点),再进行下面方式处理:
😊
思路是这样的:
将图片转换为灰度图像,并用阈值处理将白色部分分割出来。
用cv2.findContours函数找到图像中的所有轮廓,并按照轮廓面积排序。
选择最大的一个轮廓,即最外层的轮廓,并用cv2.boundingRect函数计算它的外接矩形。
用cv2.rectangle函数在原图上绘制外接矩形,或者用cv2.drawContours函数绘制轮廓本身。
import cv2
import numpy as np
# 读取图片
img = cv2.imread("image.png")
# 转换为灰度图像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 用阈值处理将白色部分分割出来
ret, thresh = cv2.threshold(gray, 250, 255, cv2.THRESH_BINARY)
# 用cv2.findContours函数找到图像中的所有轮廓,并按照轮廓面积排序
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = sorted(contours, key=cv2.contourArea, reverse=True)
# 选择最大的一个轮廓,即最外层的轮廓,并用cv2.boundingRect函数计算它的外接矩形
c = contours[0]
x, y, w, h = cv2.boundingRect(c)
# 用cv2.rectangle函数在原图上绘制外接矩形
cv2.rectangle(img, (x, y), (x + w, y + h), (0, 0, 255), 2)
# 或者用cv2.drawContours函数绘制轮廓本身
# cv2.drawContours(img, [c], -1, (0, 0, 255), 2)
# 显示结果
cv2.imshow("img", img)
cv2.waitKey(0)
cv2.destroyAllWindows()
也可以尝试另一种方式如下:
😊
你可以用以下方法来处理:
在用阈值处理将白色区域分割出来之前,先对图像进行一些预处理,如高斯模糊、中值滤波、双边滤波等,以去除噪声和锐化边缘。
在用cv2.findContours函数找到图像中的所有轮廓之后,先对轮廓进行一些筛选,如根据轮廓面积、周长、凸度、圆度等指标,去除一些不符合要求的轮廓。
在用cv2.boundingRect函数计算外接矩形之前,先对轮廓进行一些平滑,如用cv2.approxPolyDP函数对轮廓进行多边形逼近,或者用cv2.convexHull函数对轮廓进行凸包操作。
import cv2
import numpy as np
# 读取图片
img = cv2.imread("image.png")
# 转换为灰度图像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 对图像进行高斯模糊
blur = cv2.GaussianBlur(gray, (5, 5), 0)
# 用阈值处理将白色区域分割出来
ret, thresh = cv2.threshold(blur, 250, 255, cv2.THRESH_BINARY)
# 用cv2.findContours函数找到图像中的所有轮廓,并按照轮廓面积排序
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = sorted(contours, key=cv2.contourArea, reverse=True)
# 选择最大的一个轮廓,即最外层的轮廓,并用cv2.approxPolyDP函数对轮廓进行多边形逼近
c = contours[0]
epsilon = 0.01 * cv2.arcLength(c, True)
approx = cv2.approxPolyDP(c, epsilon, True)
# 用cv2.boundingRect函数计算多边形逼近后的轮廓的外接矩形
x, y, w, h = cv2.boundingRect(approx)
# 用cv2.rectangle函数在原图上绘制外接矩形
cv2.rectangle(img, (x, y), (x + w, y + h), (0, 0, 255), 2)
# 或者用cv2.drawContours函数绘制多边形逼近后的轮廓本身
# cv2.drawContours(img, [approx], -1, (0, 0, 255), 2)
# 显示结果
cv2.imshow("img", img)
cv2.waitKey(0)
cv2.destroyAllWindows()
不知道你这个问题是否已经解决, 如果还没有解决的话:概述一下
使用Sobel算子边检测器时,边缘检测并不那么理想,拉普拉斯边检测器弥补了Sobel检测器的不足,但是拉普拉斯便检测器的输出仍带有很多的噪音,它可以检测两个方向上的边,Canny边检测器在解决噪声方面优于拉普拉斯边检测器和Sobel边检测器·,Canny边检测器是一个分阶段的处理过程,他用到了迟滞性来做边数据处理,还使用了 非极大值抑制。 这一步排除非边缘像素, 仅仅保留了一些细线条(候选边缘) 。
Canny边缘检测算子是John F.Canny于 1986 年开发出来的一个多级边缘检测算法。更为重要的是 Canny 创立了边缘检测计算理论(Computational theory ofedge detection),解释了这项技术是如何工作的。Canny边缘检测算法以Canny的名字命名,被很多人推崇为当今最优的边缘检测的算法。
源码附上:
import cv2
import PIL
img = cv2.imread('lena.jpg')
gray = cv2.imread('lena.jpg', cv2.IMREAD_GRAYSCALE)
gray = cv2.resize(gray, (400, 430))
img = cv2.resize(img, (400, 430))
sober_horizontal = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=1)
sober_vertical = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize=5)
laplacian = cv2.Laplacian(img, cv2.CV_64F)
canny = cv2.Canny(img, 50, 240)
img_GanssianBlur = cv2.GaussianBlur(img, (3, 3), 0)
cv2.imshow('original', img)
cv2.imshow('Gray', gray)
cv2.imshow('sobel horizontal', sober_horizontal)
cv2.imshow('sobel vertical', sober_vertical)
cv2.imshow('Laplacation', laplacian)
cv2.imshow('Canny',canny)
cv2.imshow('GaussianBlur', img_GanssianBlur)
cv2.waitKey()