简体   繁体   中英

Can I randomly add a small image (13x12) to an array of pixels (random pixels of the same size of my small image)

I have 20 small images (that I want to put in a target area of a background image (13x12). I have already marked my target area with a circle, I have the coordinates of the circle in two arrays of pixels. Now I want to know how I can randomly add my 20 small images in random area in my arrays of pixels which are basically the target area (the drawn circle).

In my code, I was trying for just one image, if it works, I'll pass the folder of my 20 small images.

输入1

# 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)

In the expected results, the small images must be placed in the background image randomly.

If you have the center and the radius of your circle, you can easily generate random coordinates by randomly choosing an angle theta from [0, 2*pi] , calculating corresponding x and y values by cos(theta) and sin(theta) and scaling these by some random chosen scaling factors from [0, radius] . I prepared some code for you, see below.

I omitted a lot of code from yours (reading, preprocessing, saving) to focus on the relevant parts (see how to create a minimal, complete, and verifiable example ). Hopefully, you can integrate the main idea of my solution into your code on your own. If not, I will provide further explanations.

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)

The exemplary output:

产量

Caveat: I haven't paid attention, if the small images might violate the circle boundary. Therefore, some additional checks or limitations to the scaling factors must be added.


EDIT: I edited my above code. To take the below comment into account, I shift the small image by (width/2, height/2) , and limit the radius scale factor accordingly, so that the circle boundary isn't violated, neither top/left nor bottom/right.

Before, it was possible, that the boundary is violated in the bottom/right part ( n = 200 ):

违反

After the edit, this should be prevented ( n = 20000 ):

没有违反

The touching of the red line in the image is due to the line's thickness. For "safety reasons", one could add another 1 pixel distance.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM