У меня есть 20 небольших изображений (которые я хочу поместить в целевую область фонового изображения (13x12). Я уже отметил свою целевую область кружком, у меня есть координаты круга в двух массивах пикселей. Теперь я хочу чтобы узнать, как я могу случайным образом добавить свои 20 маленьких изображений в случайную область в мои массивы пикселей, которые в основном являются целевой областью (нарисованный круг).
В моем коде я пытался использовать только одно изображение, если оно сработает, я передам папку с моими 20 маленькими изображениями.
# Depencies importation
import cv2
import numpy as np
# Saving directory
saving_dir = "../Saved_Images/"
# Read the background image
bgimg = cv2.imread("../Images/background.jpg")
# Resizing the bacground image
bgimg_resized = cv2.resize(bgimg, (2050,2050))
# Read the image that will be put in the background image (exemple of 1)
# I'm just trying with one, if it works, I'll pass the folder of the 20
small_img = cv2.imread("../Images/small.jpg")
# Convert the resized background image to gray
bgimg_gray = cv2.cvtColor(bgimg, cv2.COLOR_BGR2GRAY)
# Convert the grayscale image to a binary image
ret, thresh = cv2.threshold(bgimg_gray,127,255,0)
# Determine the moments of the binary image
M = cv2.moments(thresh)
# calculate x,y coordinate of center
cX = int(M["m10"] / M["m00"])
cY = int(M["m01"] / M["m00"])
# Drawing the circle in the background image
circle = cv2.circle(bgimg, (cX, cY), 930, (0,0,255), 9)
print(circle) # This returns None
# Getting the coordinates of the circle
combined = bgimg[:,:,0] + bgimg[:,:,1] + bgimg[:,:,2]
rows, cols = np.where(combined >= 0)
# I have those pixels in rows and cols, but I don't know
# How to randomly put my small image in those pixel
# Saving the new image
cv2.imwrite(saving_dir+"bgimg"+".jpg", bgimg)
cv2.namedWindow('image', cv2.WINDOW_NORMAL)
cv2.resizeWindow("Test", 1000, 1200)
# Showing the images
cv2.imshow("image", bgimg)
# Waiting for any key to stop the program execution
cv2.waitKey(0)
В ожидаемых результатах маленькие изображения должны располагаться на фоновом изображении случайным образом.
Если у вас есть центр и радиус вашего круга, вы можете легко сгенерировать случайные координаты, случайно выбрав угол theta
из [0, 2*pi]
, вычислив соответствующие значения x
и y
с помощью cos(theta)
и sin(theta)
и масштабируя их с помощью некоторых случайно выбранных коэффициентов масштабирования из [0, radius]
. Я подготовил для вас код, см. ниже.
Я пропустил большую часть вашего кода (чтение, предварительная обработка, сохранение), чтобы сосредоточиться на соответствующих частях (см. как создать минимальный, полный и проверяемый пример). Надеюсь, вы сможете самостоятельно интегрировать основную идею моего решения в свой код. Если нет, я дам дополнительные пояснения.
import cv2
import numpy as np
# (Artificial) Background image (instead of reading an actual image...)
bgimg = 128 * np.ones((401, 401, 3), np.uint8)
# Circle parameters (obtained somehow...)
center = (200, 200)
radius = 100
# Draw circle in background image
cv2.circle(bgimg, center, radius, (0, 0, 255), 3)
# Shape of small image (known before-hand...?)
(w, h) = (13, 12)
for k in range(200):
# (Artificial) Small image (instead of reading an actual image...)
smallimg = np.uint8(np.add(128 * np.random.rand(w, h, 3), (127, 127, 127)))
# Select random angle theta from [0, 2*pi]
theta = 2 * np.pi * np.random.rand()
# Select random distance factors from center
factX = (radius - w/2) * np.random.rand()
factY = (radius - h/2) * np.random.rand()
# Calculate random coordinates for small image from angle and distance factors
(x, y) = np.uint16(np.add((np.cos(theta) * factX - w/2, np.sin(theta) * factY - h/2), center))
# Replace (rather than "add") determined area in background image with small image
bgimg[x:x+smallimg.shape[0], y:y+smallimg.shape[1]] = smallimg
cv2.imshow("bgimg", bgimg)
cv2.waitKey(0)
Примерный вывод:
Предупреждение: я не обратил внимания, могут ли мелкие изображения выходить за границы круга. Поэтому необходимо добавить некоторые дополнительные проверки или ограничения коэффициентов масштабирования.
Обновлено: Я отредактировал приведенный выше код. Чтобы учесть комментарий ниже, я сдвигаю маленькое изображение на (width/2, height/2)
и соответственно ограничиваю масштабный коэффициент радиуса, чтобы граница круга не нарушалась ни сверху/слева, ни снизу/справа.
Ранее возможно нарушение границы в нижней/правой части (n = 200
):
После редактирования это должно быть предотвращено (n = 20000
):
Касание красной линии на изображении связано с толщиной линии. Из соображений безопасности можно было бы добавить еще расстояние в 1 пиксель.
@EE2017 Если бы вы ответили на мой вопрос о фигурах, вписывающихся в круг stackoverflow.com/q/55576760/2836621, а не проигнорировали меня и снова задали почти тот же вопрос, вы бы не тратили впустую время Ганса, которое он так щедро отдает...
@MarkSetchell, я тебе ответил. Когда я ответил, я уже решил первый вопрос. Я просто искал способ преобразовать мои координаты круга, которые у меня есть, как массив пикселей. Мне очень жаль, если вы так себя чувствовали; но я не игнорировал тебя. Пожалуйста, примите во внимание мои извинения. Это сообщество слишком велико, чтобы кому-то было грустно. Еще раз прошу прощения. Позвольте мне взглянуть на ответ #HansHirse сейчас...
@HansHirse Большое спасибо, ваш ответ / код решил мою проблему. Я не думал об использовании угла. К сожалению, у меня недостаточно репутации, чтобы проверить ваш ответ, надеюсь, кто-то, кто может, сделает это. Еще раз спасибо гений.
@ EE2017 Я вижу, вы не можете голосовать в данный момент, но вы должны иметь возможность пометить мой ответ как принятый, или я ошибаюсь?
@HansHirse, я думал, что для меня это тоже деактивировано, так как я еще не могу голосовать. Теперь все готово, еще раз спасибо. Правда в том, что я полирую ваш код, чтобы заставить его делать что-то гораздо более сложное (например, получение входных изображений из разных папок, использование вложенного цикла...). Но основа ваша. Спасибо еще раз,
Ваш код хорош, но маленькие изображения не должны выходить за границу круга. Вот почему я хотел использовать координаты круга, поэтому я пытаюсь адаптировать ваш код, чтобы он соответствовал моим потребностям. Я хочу найти способ сказать своим маленьким изображениям, что они должны оставаться внутри круга. У меня есть координата круга со следующим:
# Getting the coordinates of the circle combined = bgimg[:,:,0] + bgimg[:,:,1] + bgimg[:,:,2] rows, cols = np.where(combined >= 0)
Но я пока не нашел, как это сделать. Когда я печатаю строки, столбцы представляют собой массивы пикселей. Спасибо @HansHirse