Как вырезать пробелы над изображением - PullRequest
2 голосов
/ 17 июня 2020

У меня есть проект с нейронными сетями, которые работают с такими изображениями:

Как вы видите, у него есть пустое место в верхней части поля. Мой вопрос в том, может ли это пространство влиять на результаты сети, и если да, как я могу вырезать только пустое пространство с помощью python / openCV, учитывая, что белое пространство не одинакового размера и положения во всех изображениях

Другой пример:

(откройте изображение, чтобы четко увидеть пустое пространство)

Ответы [ 2 ]

4 голосов
/ 17 июня 2020

Вот один из способов заполнить пространство черным цветом в Python / OpenCV.

Заполните все изображение белой рамкой шириной 1 пиксель. Затем залейте заполненное изображение из верхнего левого угла (0,0) черным цветом. Затем удалите границу шириной 1 пиксель. Это предполагает, что у вас нет чисто белых пикселей реальных данных по сторонам исходного изображения.

Вход 1:

enter image description here

import cv2
import numpy as np

# read image
img = cv2.imread('border_image1.jpeg')
#img = cv2.imread('border_image2.jpeg')

# convert to gray
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# add 1 pixel white border all around
pad = cv2.copyMakeBorder(gray, 1,1,1,1, cv2.BORDER_CONSTANT, value=255)
h, w = pad.shape

# create zeros mask 2 pixels larger in each dimension
mask = np.zeros([h + 2, w + 2], np.uint8)

# floodfill outer white border with black
img_floodfill = cv2.floodFill(pad, mask, (0,0), 0, (5), (0), flags=8)[1]

# remove border
img_floodfill = img_floodfill[1:h-1, 1:w-1]

# save cropped image
cv2.imwrite('border_image1_floodfilled.png',img_floodfill)
#cv2.imwrite('border_image2_floodfilled.png',img_floodfill)

# show the images
#cv2.imshow("thresh", thresh)
cv2.imshow("pad", pad)
cv2.imshow("img_floodfill", img_floodfill)
cv2.waitKey(0)
cv2.destroyAllWindows()


Результат 1:

enter image description here


Оставшаяся белая sh область вдоль диагонального края, вероятно, потому что опубликованное изображение было JPG-версией изображения PNG. JPG имеет сжатие с потерями, которое вызывает подобные эффекты. Обратите внимание, что я использовал разницу на 5 уровней серого ниже, чтобы учесть некоторое отклонение значения белого sh в этой области от чистого белого. Это уменьшило посторонний белый цвет, но не удалило его полностью. Однако он мог изменить несколько белых sh пикселей данных по сторонам изображения. Таким образом, вы можете вернуть его к 0, но в этой диагональной области останется больше белого.



Ввод 2:

enter image description here

Результат 2:

enter image description here

1 голос
/ 19 июня 2020

Вот способ обрезать изображение всего его цвета фона в Python / OpenCV.

(Я не пытался оптимизировать или упростить код. Это просто демонстрация концепции. Например, вычисление 4 средних значений может быть преобразовано в функцию def, поскольку все они являются одни и те же строки кода повторяются для каждой стороны. Если кто-то переписывает код более эффективно или оптимизирует его, пожалуйста, сделайте повторную публикацию, чтобы другие могли извлечь выгоду. черный, а остальное белое, как маска. (Я использовал cv2.inRange (), чтобы для ввода можно было использовать цветное изображение.) Затем проверяется среднее значение каждой стороны маски толщиной в 1 пиксель, чтобы увидеть, не является ли она чисто-белой (255) и с какой стороны имеет самое низкое среднее (самое темное). Если не чистый белый цвет и не самая темная сторона, тогда увеличивайте / уменьшайте значение боковой координаты (как если бы эта строка или столбец удалялась, но не делала этого на самом деле). Продолжайте проверять внутренние строки и столбцы по бокам внутрь, пока все проверенные строки и столбцы не станут чисто белыми. Это чем-то похоже на чистку лука. Затем получите окончательные координаты сторон и обрежьте изображение.

Первое изображение:

enter image description here

import cv2
import numpy as np

# read image
img = cv2.imread('border_image1.jpeg')
#img = cv2.imread('border_image2.jpeg')
h, w = img.shape[:2]

# threshold so border is black and rest is white (invert as needed)
lower = (254,254,254)
upper = (255,255,255)
mask = cv2.inRange(img, lower, upper)
mask = 255 - mask


# define top and left starting coordinates and starting width and height
top = 0
left = 0
bottom = h
right = w

# compute the mean of each side of the image and its stop test
mean_top = np.mean( mask[top:top+1, left:right] )
mean_left = np.mean( mask[top:bottom, left:left+1] )
mean_bottom = np.mean( mask[bottom-1:bottom, left:right] )
mean_right = np.mean( mask[top:bottom, right-1:right] )

mean_minimum = min(mean_top, mean_left, mean_bottom, mean_right)

top_test = "stop" if (mean_top == 255) else "go"
left_test = "stop" if (mean_left == 255) else "go"
bottom_test = "stop" if (mean_bottom == 255) else "go"
right_test = "stop" if (mean_right == 255) else "go"
#print(top_test,left_test,bottom_test,right_test)

# iterate to compute new side coordinates if mean of given side is not 255 (all white) and it is the current darkest side
while top_test == "go" or left_test == "go" or right_test == "go" or bottom_test == "go":

    # top processing
    if top_test == "go":
        if mean_top != 255:
            if mean_top == mean_minimum:
                top += 1
                mean_top = np.mean( mask[top:top+1, left:right] )
                mean_left = np.mean( mask[top:bottom, left:left+1] )
                mean_bottom = np.mean( mask[bottom-1:bottom, left:right] )
                mean_right = np.mean( mask[top:bottom, right-1:right] )
                mean_minimum = min(mean_top, mean_left, mean_right, mean_bottom)
                #print("top",mean_top)
                continue
        else:
            top_test = "stop"   

    # left processing
    if left_test == "go":
        if mean_left != 255:
            if mean_left == mean_minimum:
                left += 1
                mean_top = np.mean( mask[top:top+1, left:right] )
                mean_left = np.mean( mask[top:bottom, left:left+1] )
                mean_bottom = np.mean( mask[bottom-1:bottom, left:right] )
                mean_right = np.mean( mask[top:bottom, right-1:right] )
                mean_minimum = min(mean_top, mean_left, mean_right, mean_bottom)
                #print("left",mean_left)
                continue
        else:
            left_test = "stop"  

    # bottom processing
    if bottom_test == "go":
        if mean_bottom != 255:
            if mean_bottom == mean_minimum:
                bottom -= 1
                mean_top = np.mean( mask[top:top+1, left:right] )
                mean_left = np.mean( mask[top:bottom, left:left+1] )
                mean_bottom = np.mean( mask[bottom-1:bottom, left:right] )
                mean_right = np.mean( mask[top:bottom, right-1:right] )
                mean_minimum = min(mean_top, mean_left, mean_right, mean_bottom)
                #print("bottom",mean_bottom)
                continue
        else:
            bottom_test = "stop"    

    # right processing
    if right_test == "go":
        if mean_right != 255:
            if mean_right == mean_minimum:
                right -= 1
                mean_top = np.mean( mask[top:top+1, left:right] )
                mean_left = np.mean( mask[top:bottom, left:left+1] )
                mean_bottom = np.mean( mask[bottom-1:bottom, left:right] )
                mean_right = np.mean( mask[top:bottom, right-1:right] )
                mean_minimum = min(mean_top, mean_left, mean_right, mean_bottom)
                #print("right",mean_right)
                continue
        else:
            right_test = "stop" 


# crop input
result = img[top:bottom, left:right]

# print crop values 
print("top: ",top)
print("bottom: ",bottom)
print("left: ",left)
print("right: ",right)
print("height:",result.shape[0])
print("width:",result.shape[1])

# save cropped image
cv2.imwrite('border_image1_cropped.png',result)
#cv2.imwrite('border_image2_cropped.png',result)

# show the images
cv2.imshow("mask", mask)
cv2.imshow("cropped", result)
cv2.waitKey(0)
cv2.destroyAllWindows()


Обрезанное изображение:

enter image description here

Координаты кадрирования:

top:  132
bottom:  512
left:  3
right:  507
height: 380
width: 504



Второе изображение:

enter image description here

Обрезанное изображение:

enter image description here

Координаты культур:

top:  0
bottom:  420
left:  0
right:  512
height: 420
width: 512


Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...