'Is it possible to create a random shape on an image in python?
I need to create some spots on an image. The spots are of irregular shape (mainly I was trying to add a big circle then trying to add smaller circles on the edges of the big circle so it gets an "irregular" circular shape). Here I just showed one circle in the example. As I have a directory full of images, the size, the location, and the number of the spots need to be varied for every image. What I tried is given here:
import glob
import cv2
import numpy as np
import random
count = 0
cv_img = []
for img in glob.glob('Lenna_(test_image).png'):
n = cv2.imread(img)
for i in range(random.randint(1, 5)):
c1 = random.randrange(75,200,1)
c2 = random.randrange(70,350,1)
r1 = random.randint(8,18)
n1_img = cv2.circle(n,(c1,c2),(r1),(255,255,255),-1, lineType = 4)
cv_img.append(n1_img)
cv2.imwrite('result.png',n1_img)
count = count+1
But I want to add something like this. I did it with paint. This is the thing I want to add on the image
Solution 1:[1]
Here is the full code to add the white blobs with a black border onto some image in Python/OpenCV.
Input:
import cv2
import skimage.exposure
import numpy as np
from numpy.random import default_rng
# read input image
img = cv2.imread('lena.jpg')
height, width = img.shape[:2]
# define random seed to change the pattern
seedval = 75
rng = default_rng(seed=seedval)
# create random noise image
noise = rng.integers(0, 255, (height,width), np.uint8, True)
# blur the noise image to control the size
blur = cv2.GaussianBlur(noise, (0,0), sigmaX=15, sigmaY=15, borderType = cv2.BORDER_DEFAULT)
# stretch the blurred image to full dynamic range
stretch = skimage.exposure.rescale_intensity(blur, in_range='image', out_range=(0,255)).astype(np.uint8)
# threshold stretched image to control the size
thresh = cv2.threshold(stretch, 175, 255, cv2.THRESH_BINARY)[1]
# apply morphology open and close to smooth out and make 3 channels
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (9,9))
mask = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel)
mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel)
mask = cv2.merge([mask,mask,mask])
# add mask to input
result1 = cv2.add(img, mask)
# use canny edge detection on mask
edges = cv2.Canny(mask,50,255)
# thicken edges and make 3 channel
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3,3))
edges = cv2.morphologyEx(edges, cv2.MORPH_DILATE, kernel)
edges = cv2.merge([edges,edges,edges])
# merge edges with result1 (make black in result where edges are white)
result2 = result1.copy()
result2[np.where((edges == [255,255,255]).all(axis=2))] = [0,0,0]
# add noise to result where mask is white
noise = cv2.merge([noise,noise,noise])
result3 = result2.copy()
result3 = np.where(mask==(255,255,255), noise, result3)
# save result
cv2.imwrite('lena_random_blobs1.jpg', result1)
cv2.imwrite('lena_random_blobs2.jpg', result2)
cv2.imwrite('lena_random_blobs3.jpg', result3)
# show results
cv2.imshow('noise', noise)
cv2.imshow('blur', blur)
cv2.imshow('stretch', stretch)
cv2.imshow('thresh', thresh)
cv2.imshow('mask', mask)
cv2.imshow('edges', edges)
cv2.imshow('result1', result1)
cv2.imshow('result2', result2)
cv2.imshow('result3', result3)
cv2.waitKey(0)
cv2.destroyAllWindows()
Result1 (white blobs):
Result2 (white blobs with black border):
Result3 (noise blobs with black border):
Solution 2:[2]
Here is one way to generate random shapes in Python/OpenCV/Numpy/Skimage.
- Define a seed value for a random number generator (to change the pattern of shapes)
- Define the output width and height
- Create a random noise image
- Blur the noise image
- Stretch the blurred image to full dynamic range
- Threshold the stretched image
- Apply morphology to clean up the thresholded image
- Save the result
import cv2
import skimage.exposure
import numpy as np
from numpy.random import default_rng
# define random seed to change the pattern
seedval = 55
rng = default_rng(seed=seedval)
# define image size
width=500
height=500
# create random noise image
noise = rng.integers(0, 255, (height,width), np.uint8, True)
# blur the noise image to control the size
blur = cv2.GaussianBlur(noise, (0,0), sigmaX=15, sigmaY=15, borderType = cv2.BORDER_DEFAULT)
# stretch the blurred image to full dynamic range
stretch = skimage.exposure.rescale_intensity(blur, in_range='image', out_range=(0,255)).astype(np.uint8)
# threshold stretched image to control the size
thresh = cv2.threshold(stretch, 175, 255, cv2.THRESH_BINARY)[1]
# apply morphology open and close to smooth out shapes
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (9,9))
result = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel)
result = cv2.morphologyEx(result, cv2.MORPH_CLOSE, kernel)
# save result
cv2.imwrite('random_blobs.png', result)
# show results
cv2.imshow('noise', noise)
cv2.imshow('blur', blur)
cv2.imshow('stretch', stretch)
cv2.imshow('thresh', thresh)
cv2.imshow('result', result)
cv2.waitKey(0)
cv2.destroyAllWindows()
Result:
You can now take this image and add it to your background image to insert the white blobs over the background.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 |





