Как найти точные границы / двоичный порог металлической детали, например, сверла? - PullRequest
3 голосов
/ 11 июля 2019

Я новичок в OpenCV и Python, так что помогите мне, как 12-классник.Моя проблема в том, что я хочу определить правильный порог или край сверла для измерения, но то, что я сделал, дает много шума на изображении, из-за которого я не могу найти правильный контур объекта.

Я попытался убрать блики на изображении, а затем выровнять гистограмму, после чего я попытался использовать адаптивный порог.

gray=cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
h,s,v=cv2.split(cv2.cvtColor(img, cv2.COLOR_BGR2HSV))

bgi=cv2.GaussianBlur(gray, (3, 3), 1.0)
rn_gr = cv2.fastNlMeansDenoising(bgi,None,10,7,21)

equ = cv2.equalizeHist(rn_gr)
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))
cl1 = clahe.apply(rn_gr)

nonSat = s < 40
disk = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(3,3))    
nonSat = cv2.erode(nonSat.astype(np.uint8), disk) 
v2 = v.copy()    
v2[nonSat == 0] = 0;  
glare = v2 > 200;
glare = cv2.dilate(glare.astype(np.uint8), disk);
glare = cv2.dilate(glare.astype(np.uint8), disk);    
corrected = cv2.inpaint(img, glare, 5, cv2.INPAINT_NS)
object=corrected[485:1665,225:335]
gray_co=cv2.cvtColor(object, cv2.COLOR_BGR2GRAY)
bgi_co=cv2.GaussianBlur(gray_co, (3, 3), 1.0)
rn_gr_co = cv2.fastNlMeansDenoising(bgi_co,None,10,7,21)
cl2 = clahe.apply(rn_gr_co)

v=np.median(cl2)
lower=int(max(0,(1.0-sigma)*v))
upper=int(min(255,(1.0+sigma)*v))
print(lower,upper)
edged = cv2.Canny(cl2,lower,upper)
th3_o = cv2.adaptiveThreshold(obj,upper,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY,11,2)
        th3_o=~th3_o

#kernel = np.ones((5,5),np.uint8)
kernel=cv2.getStructuringElement(cv2.MORPH_RECT,(3,3))
morph = cv2.morphologyEx(th3_o, cv2.MORPH_GRADIENT, kernel)
closing = cv2.morphologyEx(th3_o, cv2.MORPH_CLOSE, kernel)
opening = cv2.morphologyEx(closing, cv2.MORPH_OPEN, kernel)

contours_o, hierarchy = cv2.findContours(th3_o,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)
for cnt_o in contours_o:
   epsilon = 0.1*cv2.arcLength(cnt_o,True)
   approx = cv2.approxPolyDP(cnt_o,epsilon,True)
   con_o = cv2.drawContours(th3_o, contours_o, -1, (0,255,0), 3)
plt.imshow(con_o)
plt.show()

мой ожидаемый результат должен выглядеть так, как я рисуюс границами необходимое изображение но я получаю что-то вроде этого нежелательное изображение

1 Ответ

4 голосов
/ 11 июля 2019

Я думаю, что вы используете слишком много операций и продумываете подход к обнаружению контуров. Вы используете слишком много последовательных операций, не понимая цели каждого шага. Как правило, предварительная обработка выполняется для изображения, чтобы удалить шум или сгладить изображения (гауссово / медианное / двустороннее размытие). Затем на изображении делается какая-то двоичная сегментация, чтобы изолировать контуры (определение порога, обнаружение края Кэнни). Отсюда морфологические преобразования могут быть выполнены для дальнейшей фильтрации или усиления, таких как размывание или расширение. Затем вы можете найти контуры и выполнить дополнительную фильтрацию (площадь контура, близость, соотношение сторон). Для этой проблемы идея состоит в том, чтобы упростить стратегический подход, чтобы изолировать внешний контур


Вот потенциальный подход

  • Преобразование в оттенки серого и медианное размытие изображения для удаления шума и сглаживания изображения
  • Пороговое изображение
  • Поиск контуров
import cv2

image = cv2.imread('1.jpg')

blur = cv2.medianBlur(image, 7)
gray = cv2.cvtColor(blur, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray,160,255, cv2.THRESH_BINARY_INV)[1]

cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]

for c in cnts:
    cv2.drawContours(image, [c], -1, (36, 255, 12), 2)

cv2.imshow('thresh', thresh)
cv2.imshow('image', image)
cv2.imwrite('image.png', image)
cv2.waitKey()

image

...