Обрезать область определенного цвета и удалить области с шумом (Python+OpenCV)
У меня проблема при получении двоичного изображения из цветных изображений. cv2.inRange()
функция используется для получения mask
изображения (аналог с пороговым значением), и я хочу удалить ненужные части, сводя к минимуму размывание mask
изображений. Самая большая проблема в том, что mask
s не извлекаются регулярно.
образцы
Crack:
Типичный
Идеальный вариант:
Моим первым объектом является создание второго изображения в качестве третьего. Я думаю, получая контур, который имеет наибольшую площадь и удаляя другие контуры (также для mask
) будет работать. Но не могу не найти как.
Вторая проблема заключается в том, что идея, которую я описал выше, не будет работать для первого изображения (трещины). Этот вид изображений может быть отброшен. Но в любом случае это должно быть помечено как трещина. Пока у меня нет идей для этого.
Что я сделал
Вот входное изображение и коды 42_1.jpg
class Real:
__ex_low=np.array([100,30,60])
__ex_high=np.array([140,80,214])
__ob_low=np.array([25,60,50]) #27,65,100])
__ob_high=np.array([50,255,255]) #[45,255,255])
def __opening(self, mask):
kernel = np.ones((3,3), np.uint8)
op = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel)
return op
def __del_ext(self, img_got):
img = img_got[0:300,]
hsv = cv2.cvtColor(img,cv2.COLOR_BGR2HSV)
mask = cv2.inRange(hsv, self.__ex_low, self.__ex_high)
array1 = np.transpose(np.nonzero(mask))
array2 = np.nonzero(mask)
temp=array1.tolist()
xmin=min(array2[0]) #find the highest point covered blue
x,y,channel=img.shape
img=img[xmin:x,]
hsv=hsv[xmin:x,]
return img, hsv
def __init__(self, img_got):
img, hsv = self.__del_ext(img_got)
mask_temp = cv2.inRange(hsv, self.__ob_low, self.__ob_high)
mask = self.__opening(mask_temp)
array1 = np.transpose(np.nonzero(mask))
array2 = np.nonzero(mask)
ymin=min(array2[1])
ymax=max(array2[1])
xmin=min(array2[0])
xmax=max(array2[0])
self.x = xmax-xmin
self.y = ymax-ymin
self.ratio = self.x/self.y
# xmargin = int(self.x*0.05)
#ymargin = int(self.y*0.05)
self.img = img[(xmin):(xmax),(ymin):(ymax)]
self.mask = mask[(xmin):(xmax),(ymin):(ymax)]
#models = glob.glob("D:/Python36/images/motor/*.PNG")
img = cv2.imread("D:/Python36/images/0404/33_1.jpg")#<- input image
#last_size = get_last_size(models[-1])
#m2= Model(models[39],last_size)
r1 = Real(img)
cv2.imshow("2",r1.img)
cv2.imshow("3",r1.mask)
Было бы здорово, если бы коды были написаны на python3
, но все будет хорошо.
1 ответ
В общем, с вашим методом все в порядке, кроме неправильного ядра для удаления горизонтальных линий.
Я заканчиваю это в следующих шагах:
(1) Читать и конвертировать в HSV
(2) Найти целевую область желтого цвета в HSV
(3) morph-op для удаления линий горизонта
(4) обрезать регион
Это результат:
Код:
#!/usr/bin/python3
# 2018/04/16 13:20:07
# 2018/04/16 14:13:03
import cv2
import numpy as np
## (1) Read and convert to HSV
img = cv2.imread("euR2X.png")
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
## (2) Find the target yellow color region in HSV
hsv_lower = (25, 100, 50)
hsv_upper = (33, 255, 255)
mask = cv2.inRange(hsv, hsv_lower, hsv_upper)
## (3) morph-op to remove horizone lines
kernel = np.ones((5,1), np.uint8)
mask2 = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel)
## (4) crop the region
ys, xs = np.nonzero(mask2)
ymin, ymax = ys.min(), ys.max()
xmin, xmax = xs.min(), xs.max()
croped = img[ymin:ymax, xmin:xmax]
pts = np.int32([[xmin, ymin],[xmin,ymax],[xmax,ymax],[xmax,ymin]])
cv2.drawContours(img, [pts], -1, (0,255,0), 1, cv2.LINE_AA)
cv2.imshow("croped", croped)
cv2.imshow("img", img)
cv2.waitKey()
References
: