基于OpenCV获取目标区域

目标提取

预备知识

  • 了解opencv的一些基础函数(二值化,腐蚀,膨胀,开闭运算等)
  • 了解python的简单语法

目标

提取出图片中的圆形工件
在这里插入图片描述

思路

  1. 通过opencv的imread函数读入样本图片,转化为灰度图片(不转化灰度图片,二值化化会报错)
  2. 经过高斯滤波后,选择合适的阈值来二值化图片。
  3. 经过开闭运算优化二值化图片,然后调用findContours检测边缘。
  4. 绘制边缘,取出目标区域。

难点

  • 一个合适的阈值很难确定
难点解决

阈值的选择:通过一个可以改变的阈值的来测试二值图像效果。
代码演示:

# 导入opencv的库
import cv2

# 加载样本图片
img = cv2.imread("F:/copy/7.jpg")
# 转化为灰度图片,高斯滤波
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(gray, (5, 5), 0)

# 定义一个滑动条
def trackbarCallback(): # 回调函数
	pass
cv2.createTrackbar("thresh", "original", 0, 255, trackbarCallback)

# 创建一个窗口
cv2.nameWindow("original")
while True:
	# 获取滑动条的thresh值
	thresh = cv2.getTrackbarPos('thresh', 'original')
	# 二值化图片
	img_thresh = cv2.threshold(blur, thresh, 255, cv2.THRESH_BINARY)[1]
	k = cv2.WaitKey(0) & 0xff
	if k == 27# 按esc键结束
		break
cv2.destroyAllWindows()

运行结果:
当thresh为0时,只要大于阈值的颜色值就设置为255,因此显示为白色,通过滑动选择合适的阈值。
在这里插入图片描述
经过筛选,选出合适的阈值为67。
在这里插入图片描述

目标实现

已经选择合适的阈值(阈值为67),接下来进行目标的实现。

import cv2
import numpy as np

# 真实的图片
real = cv2.imread("F:/copy/7.jpg")

# 我的样本图片尺寸过大,因此需要修改图片大小。若图片正常,可以忽略此步骤
h = real.shape[0]
w = real.shape[1]
# 设置你想要的宽度
width = 600
r = width / float(w)
dim = (width, int(h * r))
real = cv2.resize(real,dim.interpolation=cv2.INTER_AREA)
# 图片的左右边缘出现了传送带的部分,我选择截取掉这些无用部分
real = real[0:, 50:real.shape[1] - 50]
cv2.namedWindow("real")
cv2.imshow("real", real)

# 二值化
gray = cv2.cvtColor(real, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray, (5, 5), 0)
thresh = cv2.threshold(blurred, 67, 255, cv2.THRESH_BINARY)[1]
cv2.namedWindow("Image")
cv2.imshow("Image", thresh)

# 绘制轮廓
img = thresh
contour, hierarchy = cv2.findContours(img.copy(), cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(real, contour, -1, (0, 255, 0), 2)
cv2.namedWindow("draw")
cv2.imshow("draw", real)

# 把前景部分提取,放入一张黑色图片上
cv2.namedWindow("fill")
mask = np.zeros(real.shape).astype(real.dtype)
# 将contours里填充为白色
cv2.fillPoly(mask, contour, (255, 255, 255))
cv2.imshow("fill", mask)
result = cv2.bitwise_and(real, mask)
cv2.namedWindow("result")
cv2.imshow("resultS", result)


cv2.waitKey(0)
cv2.destroyAllWindows()

运行结果:(只展示最后一张结果图片)
在这里插入图片描述

交流

在这里插入图片描述
关注回复"提取目标",即可获取源码和测试样本

猜你喜欢

转载自blog.csdn.net/weixin_44736584/article/details/105162103