如何更有效提取图像中的六边形、圆形

问题遇到的现象和发生背景

使用了很多办法尝试优化图像中的六边形和圆孔,但实际上没有什么明显优化效果,想请教一下还有什么更好的办法能够获取?

img


img

我的解答思路和尝试过的方法

import cv2 as cv
import numpy as np
import argparse
import matplotlib.pyplot as plt

def get_parser():
parser=argparse.ArgumentParser(description="ALL SOLID ARGS")
parser.add_argument("-filename",default="C:/Users/JayLee/Desktop/OpenCV/contours/onsite samples/stainles steel.jpg")
parser.add_argument("-IMAGE_SIZE_K",type=float,default=0.4)
parser.add_argument("-IMAGE_K_HEIGHT_UP",type=float,default=0.23)
parser.add_argument("-IMAGE_K_HEIGHT_DOWN",type=float,default=0.884)
parser.add_argument("-IMAGE_K_WIDTH_LEFT",type=float,default=0.08)
parser.add_argument("-IMAGE_K_WIDTH_RIGHT",type=float,default=0.96)
parser.add_argument("-GAUSIAN_SIGMA_X",type=int,default=1)
parser.add_argument("-ADAP_BLOCK_SIZE",type=int,default=3)
parser.add_argument("-ADAP_C",type=float,default=3.7)
parser.add_argument("-APPROX_EPSILON_K",type=float,default=0.0001)
parser.add_argument("-CRITICAL_AREA_K",type=float,default=0.008)

return parser

dilate_kernel=np.ones((3,3),np.uint8)
erode_kernel=cv.getStructuringElement(cv.MORPH_CROS,(3,3))

parser=get_parser()
args=parser.parse_args()

src=cv.imread(args.filename)

image=cv.resize(src,None,fx=args.IMAGE_SIZE_K,fy=args.IMAGE_SIZE_K,interpolation=cv.INTER_CUBIC)
height,width=image.shape[:2]
image=image[int(heightargs.IMAGE_K_HEIGHT_UP):int(heightargs.IMAGE_K_HEIGHT_DOWN),
int(widthargs.IMAGE_K_WIDTH_LEFT):int(widthargs.IMAGE_K_WIDTH_RIGHT),:]

height,width=image.shape[:2]

gray=cv.cvtColor(image,cv.COLOR_RGB2GRAY)

sobelx=cv.Sobel(gray,cv.CV_64F,1,0)
sobely=cv.Sobel(gray,cv.CV_64F,0,1)
sobel=cv.addWeighted(cv.convertScaleAbs(sobelx),0.5,cv.convertScaleAbs(sobely),0.5,0)
cv.imshow("sobel",sobel)

scharrx=cv.convertScaleAbs(cv.Scharr(gray,cv.CV_64F,1,0))
scharry=cv.convertScaleAbs(cv.Scharr(gray,cv.CV_64F,0,1))
scharr=cv.addWeighted(scharrx,0.5,scharry,0.5,0)
cv.imshow("scharr",scharr)

laplacian=cv.convertScaleAbs(cv.Laplacian(gray,cv.CV_64F))
cv.imshow("laplacian",laplacian)

blurred=cv.GausianBlur(gray,(3,3),sigmaX=args.GAUSIAN_SIGMA_X)

thresh=cv.adaptiveThreshold(blurred,255,cv.ADAPTIVE_THRESH_MEAN_C,
cv.THRESH_BINARY_INV,
blockSize=args.ADAP_BLOCK_SIZE,
C=args.ADAP_C)

cnts=cv.findContours(thresh,cv.RETR_LIST,cv.CHAIN_APPROX_SIMPLE)[0]

approx_cnts=[]
for a in cnts:
length=cv.arcLength(a,True)
approx=cv.approxPolyDP(a,args.APPROX_EPSILON_K*length,True)
approx_cnts.append(approx)

areas=[]
areas_id=[]
for c in range(len(approx_cnts)):
area=cv.contourArea(approx_cnts[c])
areas.append(area)
areas_id.append(id)

critical_area=args.CRITICAL_AREA_K*max(areas)
choiced_cnts=[]
for c in range(len(areas)):
if areas[c]>critical_area:
temp=approx_cnts[c]
choiced_cnts.append(temp)

choiced_image=np.zeros((height,width),dtype=np.uint8)
choiced_image=cv.drawContours(choiced_image,np.array(choiced_cnts,dtype=object),-1,color=255,1)

temp=choiced_image.copy()
dilated=cv.dilate(temp,dilate_kernel)
eroded=cv.erode(dilated,erode_kernel)

new_cnts=cv.findContours(eroded,cv.RETR_LIST,cv.CHAIN_APPROX_SIMPLE)[0]
new_apprxo_cnts=[]
for nc in new_cnts:
epsilon=0.01
approx=cv.approxPolyDP(nc,epsilon,True)
new_apprxo_cnts.append(approx)
temp=np.zeros((height,width),np.uint8)
for c in range(len(new_apprxo_cnts)):
if c%2==0:
temp=cv.drawContours(temp,np.array(new_apprxo_cnts,dtype=object),c,
color=255,1)

plt.subplot(3,4,1)
plt.imshow(cv.cvtColor(src,cv.COLOR_RGB2BGR))
plt.title("init image")
plt.subplot(3,4,2)
plt.imshow(gray,cmap="gray")
plt.title("gray image")
plt.subplot(3,4,3)
plt.imshow(blurred,cmap="gray")
plt.title("blurred")
plt.subplot(3,4,4)
plt.imshow(thresh,cmap="gray")
plt.title("thresh")
plt.subplot(3,4,5)
plt.imshow(choiced_image,cmap="gray")
plt.title("choiced_image")
plt.subplot(3,4,6)
plt.imshow(dilated,cmap="gray")
plt.title("dilated")
plt.subplot(3,4,7)
plt.imshow(eroded,cmap="gray")
plt.title("eroded")
plt.subplot(3,4,8)
plt.imshow(temp,cmap="gray")
plt.title("temp")
plt.subplot(3,4,9)
plt.imshow(sobel,cmap="gray")
plt.title("sobel")
plt.subplot(3,4,10)
plt.imshow(scharr,cmap="gray")
plt.title("scharr")
plt.subplot(3,4,11)
plt.imshow(laplacian,cmap="gray")
plt.title("laplacian")

plt.show()
cv.waitKey()
cv.destroyAllWindows()

我想要达到的结果

清晰获取图像中的六边形和圆孔

麻烦提供可解决问题代码及相关程序解释

要不尝试一下深度学习吧,用yolo检测

opencv的话,可以先滤波,降低噪声影响,六角形和圆形边框rgb变化很剧烈,可以从这里入手

用颜色范围,取色器取出最淡线条和最深线条颜色,

模板匹配

给你个思路,希望有帮助!
第一步 ,将圆形边缘坐标文件里的坐标整理一下

第二步, 加载原图,创建掩膜

第三步 ,将连接起来的区域对应的数组和原图对应位置按位相与,这样就截取到了需要的区域了

在提取图形前先做一下预处理,这样提取到的图形更符合想要的效果。