Я пытаюсь выполнить вычитание фона для изображений c, используя Python и OpenCV, вот мой текущий метод вычитания фона:
def subtract_background(image: np.ndarray):
img = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
plt.imshow(img, cmap='Greys_r')
plt.show(block=True)
imgNoShadows = remove_shadows(img)
gsImg = cv2.cvtColor(imgNoShadows, cv2.COLOR_RGB2GRAY)
# plt.imshow(gsImg, cmap='Greys_r')
blur = cv2.GaussianBlur(gsImg, (55, 55), 0)
plt.imshow(blur, cmap='Greys_r')
plt.show(block=True)
retOtsu, imgOtsu = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)
plt.imshow(imgOtsu, cmap='Greys_r')
plt.show(block=True)
tempKernel = np.ones((10, 10), np.uint8)
closedImg = cv2.morphologyEx(imgOtsu, cv2.MORPH_CLOSE, tempKernel)
plt.imshow(closedImg, cmap='Greys_r')
# contours
contours, hierarchy = cv2.findContours(closedImg, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
print(len(contours))
# creating a mask image for background subtraction using the contour
x, y = closedImg.shape
black_img = np.empty([x, y, 3], dtype=np.uint8)
black_img.fill(0)
plt.imshow(black_img, cmap='Greys_r')
plt.show(block=True)
index = find_contour(contours, img)
cnt = contours[index]
mask = cv2.drawContours(black_img, [cnt], 0, (255, 255, 255), -1)
plt.imshow(mask)
plt.show(block=True)
return mask
maskedImg = cv2.bitwise_and(img, mask)
whitePx = [255, 255, 255]
blackPx = [0, 0, 0]
finalImg = maskedImg
h, w, channels = finalImg.shape
for x in range(0, w):
for y in range(0, h):
channels_xy = finalImg[y, x]
if all(channels_xy == blackPx):
finalImg[y, x] = whitePx
plt.imshow(finalImg)
plt.show(block=True)
return finalImg
Это, кажется, обнаруживает большую часть фона и вычитает это правильно, но тени оказались трудными, и они продолжают проходить через все пороги и контуры. Я пытался использовать cv2.createBackgroundSubtractorMOG2()
, но он возвращает полностью черное изображение. Этот метод, кажется, работает только для кадров в видео, так как я уверен, что MOG2 узнает, какая тень основана на прошлых кадрах. Я пробовал это для обнаружения теней для моих изображений c:
def remove_shadows(image: np.ndarray) -> np.ndarray:
rgbPlanes = cv2.split(image)
resultPlanes = []
resultNormalPlanes = []
for plane in rgbPlanes:
dilatedImg = cv2.dilate(plane, np.ones((7, 7), np.uint8))
bgImg = cv2.medianBlur(dilatedImg, 21)
diffImg = 255 - cv2.absdiff(plane, bgImg)
normImg = cv2.normalize(diffImg, None, alpha=0, beta=255, norm_type=cv2.NORM_MINMAX, dtype=cv2.CV_8UC1)
resultPlanes.append(diffImg)
resultNormalPlanes.append(normImg)
result = cv2.merge(resultPlanes)
resultNormal = cv2.merge(resultNormalPlanes)
plt.imshow(result)
plt.show(block=True)
plt.imshow(resultNormal)
plt.show(block=True)
return resultNormal
Этот метод фактически делает обнаружение фона менее эффективным. Существует ли эффективное решение для обнаружения теней изображения c?