I was working to reproduce an optical illusion that you find here(image) but I having trouble adding horizontal lines inside of the circles: My attempt so far:
-Detect the certain colors of the circles
-Detect contours, and extract circle center points, and radius
-Then try to draw horizontal lines (which I failed)
Here is my code:
import numpy as np
import cv2
img = 255*np.ones((800, 800, 3), np.uint8)
height, width,_ = img.shape
#filling the image with lines
for i in range(0, height, 15):
cv2.line(img, (0, i+3), (width, i+3), (255, 0, 0), 4)
cv2.line(img, (0, i+8), (width, i+8), (0, 255, 0), 4)
cv2.line(img, (0, i+13), (width, i+13), (0, 0, 255), 4)
#adding 5 gray circles
for i in range(0, height, int(height/5)):
cv2.circle(img, (i+50, i+50), 75, (128, 128, 128), -1)
#finding rannge of gray circles
lower=np.array([127,127,127])
upper=np.array([129,129,129])
mask = cv2.inRange(img, lower, upper)
#contours
contours, _ = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
for cnt in contours:
#draw circles around the contours
coordinates = cv2.minEnclosingCircle(cnt)
#coordinates and radius:
center = (int(coordinates[0][0]), int(coordinates[0][1]))
radius = int(coordinates[1])
#I wanted to do a sanity check before the for loop (I added a line the longest line should be 2*radius)
cv2.line(img, (center[0]-radius, center[1]), (center[0]+radius, center[1]), (0, 0, 0), 4)
for i in range(0, radius, int(radius/5)):
cv2.line(img, (center[0]-radius+i, center[1]+i), (center[0]+radius-i, center[1]+i), (0, 0, 0), 4)
cv2.line(img, (center[0]-radius+i, center[1]-i), (center[0]+radius-i, center[1]-i), (0, 0, 0), 4)
cv2.imwrite('munker.png',img)
As you can see the values in the for loop are not proportional to the boundaries of the circle, so the lines are short(except the longest line). What am I missing here?
I tried the Hough transform but I had a similar problem.
For more clarity, I write a code to show what I wanted:
for i in range(0, 360, 15):
x = int(center[0] + radius * np.cos(np.deg2rad(i)))
y = int(center[1] + radius * np.sin(np.deg2rad(i)))
cv2.line(img, (x,y), (x, y), (0, 255, 255), 10)
I want to merge the yellow dots with horizontal lines. But my math is finished right here. Sorry, it's long, I was just trying to make things clear. Thank you for your time.
As @fmw42 pointed out in the comment, splitting the RGB channels and applying a mask is very effective at being able to fill the inside of the circles with horizontal lines.
import numpy as np
import cv2
img = 255*np.ones((800, 800, 3), np.uint8)
height, width,_ = img.shape
for i in range(0, height, 15):
cv2.line(img, (0, i+3), (width, i+3), (255, 0, 0), 4)
cv2.line(img, (0, i+8), (width, i+8), (0, 255, 0), 4)
cv2.line(img, (0, i+13), (width, i+13), (0, 0, 255), 4)
b, g, r = cv2.split(img)
mask_b = np.zeros((height, width), np.uint8)
mask_g = np.zeros((height, width), np.uint8)
mask_r = np.zeros((height, width), np.uint8)
for i in range(0, height, int(height/5)):
cv2.circle(mask_b, (i, i), 75, 255, -1)
cv2.circle(mask_g, (i, i), 75, 255, -1)
cv2.circle(mask_r, (i, i), 75, 255, -1)
#apply the mask to the channels
b = cv2.bitwise_and(b, b, mask=mask_b)
g = cv2.bitwise_and(g, g, mask=mask_g)
r = cv2.bitwise_and(r, r, mask=mask_r)
#merge the channels
img = cv2.merge((b, g, r))
cv2.imshow('image', img)
cv2.waitKey(0)