圆型凹槽检测(python+opencv)
亮度均匀算法+霍夫+分块滤波
原图:
# -*- coding: utf-8 -*-
"""
Created on Wed Jan 6 16:01:52 2021
@author: HUANGYANGLAI
"""
import cv2 as cv
import math
import numpy as np
import matplotlib.pyplot as plt
def unevenLightCompensate(img, blockSize):
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)#读取灰度图片
average = np.mean(gray)#求均值
rows_new = int(np.ceil(gray.shape[0] / blockSize))#返回上整数
cols_new = int(np.ceil(gray.shape[1] / blockSize))
print('rows_new',rows_new)
print('cols_new',cols_new)
blockImage = np.zeros((rows_new, cols_new), dtype=np.float32)
for r in range(rows_new):
for c in range(cols_new):
rowmin = r * blockSize
rowmax = (r + 1) * blockSize
if (rowmax > gray.shape[0]):#到达边界
rowmax = gray.shape[0]
colmin = c * blockSize
colmax = (c + 1) * blockSize
if (colmax > gray.shape[1]):#到达边界
colmax = gray.shape[1]
imageROI = gray[rowmin:rowmax, colmin:colmax]
temaver = np.mean(imageROI)
blockImage[r, c] = temaver
blockImage = blockImage - average
blockImage2 = cv.resize(blockImage, (gray.shape[1], gray.shape[0]), interpolation=cv.INTER_CUBIC)
gray2 = gray.astype(np.float32)
dst = gray2 - blockImage2
dst = dst.astype(np.uint8)
dst = cv.GaussianBlur(dst, (3, 3), 0)
print('haha',dst.shape)
dst = cv.cvtColor(dst, cv.COLOR_GRAY2BGR)
return dst
def rgb2gray(img):
h=img.shape[0]
w=img.shape[1]
img1=np.zeros((h,w),np.uint8)
for i in range(h):
for j in range(w):
img1[i,j]=0.144*img[i,j,0]+0.587*img[i,j,1]+0.299*img[i,j,1]
return img1
def dis(x1,x2,y1,y2):
return (x1-x2)**2+(y1-y2)**2
def FindPointsOnCircle(Image,cx,cy,r,dr):
out=Image.copy()
H,W=Image.shape
for x in range(W):
for y in range(H):
d=dis(x,cx,y,cy)
if d<(r-dr)**2 or d>(r+dr)**2:
out[y,x]=0
return out
def findmaxRadius( image, Cir, dr):#image是大致区域范围,cir在圆形范围内检测到的圆形,dr带宽
CirIndex=[]
(H,W)=image.shape
H=H/2
W=W/2
for data in Cir:
if data[0]>= W-dr and data[0] <=W+dr and data[1]>= H-dr and data[1] <=H+dr:
CirIndex.append(data)
return CirIndex
def first_order(img):#一阶画圆
otsuimage=img
sobelx=cv.Sobel(otsuimage,cv.CV_64F,1,0,ksize=3)
sobelx=cv.convertScaleAbs(sobelx)
sobely=cv.Sobel(otsuimage,cv.CV_64F,0,1,ksize=3)
sobely=cv.convertScaleAbs(sobely)
sobelimage=cv.addWeighted(sobelx,0.5,sobely,0.5,0)
return sobelimage
def nightcircle(img):
data=img
data0=data[0:3]
data1=data[3:6]
data2=data[6:9]
indey0=np.argsort(data0,0)[:,0]
data0=data0[indey0,:]
indey1=np.argsort(data1,0)[:,0]
data1=data1[indey1,:]
indey2=np.argsort(data2,0)[:,0]
data2=data2[indey2,:]
print('0',data0)
print('1',data1)
print('2',data2)
data=np.vstack((data0,data1,data2))
return data
def Houghtrans(img,para1,para2,minRadius,maxRadius):
circle=cv.Houghcircles(img,cv.HOUGH_GRADIENT,1,para1,param1=1,param2=para2,minRadius=minRadius,maxRadius=maxRadius)
return circle
def onecircle(img,j,dr):
k=0
for i in data:
k=k+1
if(k>10):
break
cv.circle(image1,(i[0],i[1]),i[2],(0,255,0),2)
print(i[0])
print(i[1])
cv.circle(image1,(i[0],i[1]),2,(0,0,255),3)
cv.circle(image1,(i[0],i[1]),10,(0,0,255),3)
if(k==j):#找到第几个圆然后进行保
cut=image2[(i[1]-i[2]-5)*4:(i[1]+i[2]+5)*4,4*(i[0]-i[2]-5):(i[0]+i[2]+5)*4,:]
cut1=cut.copy()
cut=cv.Canny(cut,20,100)
circles=cv.HoughCircles(cut,cv.HOUGH_GRADIENT,1,50,param1=1,param2=23,minRadius=30,maxRadius=300)
circles=np.uint16(np.around(circles))
data1=circles[0,]
#Cir = findmaxRadius(cut,data1,20)
Cir = findmaxRadius(cut,data1,dr)
print('Cir:',Cir)
Cir=list(Cir)
out=FindPointsOnCircle(cut,Cir[0][0],Cir[0][1],Cir[0][2],3)
C=cv.HoughCircles(out,cv.HOUGH_GRADIENT,1,60,param1=1,param2=13,minRadius=30,maxRadius=200)
C=C[0,]
cv.circle(cut1,(int(C[0][0]),int(C[0][1])),int(C[0][2]),(0,255,0),2)
cv.circle(image2,(int(C[0][0]+4*(i[0]-i[2]-5)),int(C[0][1]+(i[1]-i[2]-5)*4)),int(C[0][2]),(0,255,0),2)
center=(int(C[0][0]+4*(i[0]-i[2]-5)),int(C[0][1]+(i[1]-i[2]-5)*4))
radial=C[0][2]
return image2,center,radial
if __name__=='__main__':
image=cv.imread("first.jpg")
image2=image.copy()
blockSize = 16#分成16块
h,w=image.shape[0:2]
print(h)
print(w)
image = cv.resize(image,(int(w/4),int(h/4)))
image1=image.copy()
image=cv.GaussianBlur(image,(5,5),3)
image = unevenLightCompensate(image, blockSize)
grayimage=rgb2gray(image)
otsuimage=grayimage
sobelimage=first_order(otsuimage)#一阶
circles=cv.HoughCircles(sobelimage,cv.HOUGH_GRADIENT,1,50,param1=1,param2=56,minRadius=19,maxRadius=40)
circles=np.uint16(np.around(circles))
##############################由于霍夫变换检测的圆是随机的故开始调整###################
data=circles[0,]#所有圆的信息相关
index=np.argsort(data,0)[:,1]
data=data[index,:]
data=nightcircle(data)
#################################圆调整(从上到下从左到右)################
image2,center,radial=onecircle(data, 4,20)
cv.imshow('opop',image2)
print('圆心坐标',center)
print('半径',radial)
cv.waitKey(0)
cv.destroyAllWindows()
通过算法然后滤波得到
选择的某一个圆消除噪点
最后效果