Related
I have the code, where it draws the line over the image, but here I can see directly the result.
How can I change the code in order to observe how the line is drawing.
import cv2
path = r'test.jpeg'
image = cv2.imread(path)
window_name = 'Image'
start_point = (0, 0)
end_point = (250, 250)
color = (0, 255, 0)
thickness = 9
image = cv2.line(image, start_point, end_point, color, thickness)
cv2.imshow(window_name, image)
cv2.waitKey()
Try this for example. I did not add image. You can suit yourself.
import cv2
import numpy as np
import time
Frame_out = np.zeros((500, 640, 3),np.uint8)
a = 1
while a < 255:
cv2.line(Frame_out,(0,0),(a*2,a*2),(0,0,255-a),9)
time.sleep(0.05)
cv2.imshow('Animation', Frame_out)
cv2.line(Frame_out,(0,0),(a*2,a*2),(0,0,0),9)
a += 2
if(a > 254):
a = 1
k = cv2.waitKey(10)
if k == 27:
break
cv2.destroyAllWindows()
I am making a object detection project.
I have my code. And I have written it by following a tutorial. In the tutorial, the guy drew a rectangle in opencv for every single object which is detected.
But I want to change the rectangle to triangle or Arrow.
let me explain with code===>
In my function, I detect objects.
And here I draw rectangle for detected objects==>
cv2.rectangle(img, (x, y), (x+w,y+h), (255, 0 , 255), 2)
But I want to change this rectangle to a triangle.(And I want to set position of triangle to above of object.
Just like in these images:::
This is the object detection with triangle
[![enter image description here][1]][1]
This is the thing that what I want to make instead of rectangle:::
[![enter image description here][2]][2]
How Can I make a triangle/arrow with positions of my detected objects?
All of my code is here==>
from os.path import sep
import cv2 as cv2
import numpy as np
import json
# Camera feed
cap_cam = cv2.VideoCapture(0)
ret, frame_cam = cap_cam.read()
hey = 0
print(cv2. __version__)
whT = 320
confThreshold =0.5
nmsThreshold= 0.2
classesFile = "coco.names"
classNames = []
with open(classesFile, 'rt') as f:
classNames = f.read().rstrip('\n').split('\n')
print(classNames)
## Model Files
modelConfiguration = "custom-yolov4-tiny-detector.cfg"
modelWeights = "custom-yolov4-tiny-detector_last.weights"
net = cv2.dnn.readNetFromDarknet(modelConfiguration, modelWeights)
net.setPreferableBackend(cv2.dnn.DNN_BACKEND_OPENCV)
net.setPreferableTarget(cv2.dnn.DNN_TARGET_CPU)
def findObjects(outputs,img):
global hey
global previousHey
hT, wT, cT = img.shape
bbox = []
classIds = []
confs = []
for output in outputs:
for det in output:
scores = det[5:]
classId = np.argmax(scores)
confidence = scores[classId]
if confidence > confThreshold:
w,h = int(det[2]*wT) , int(det[3]*hT)
x,y = int((det[0]*wT)-w/2) , int((det[1]*hT)-h/2)
bbox.append([x,y,w,h])
classIds.append(classId)
confs.append(float(confidence))
global indicates
indices = cv2.dnn.NMSBoxes(bbox, confs, confThreshold, nmsThreshold)
hey = 0
for i in indices:
i = i[0]
box = bbox[i]
x, y, w, h = box[0], box[1], box[2], box[3]
# print(x,y,w,h)
cv2.rectangle(img, (x, y), (x+w,y+h), (255, 0 , 255), 2)
#cv2.line(img, (350,400), (x, y), (255,0,0), 4)
#cv2.line(img, (400,400), (x + 50 , y), (255,0,0), 4)
#cv.putText(img,f'{classNames[classIds[i]].upper()} {int(confs[i]*100)}%',
#(x, y-10), cv.FONT_HERSHEY_SIMPLEX, 0.6, (255, 0, 255), 2)
print('success')
hey = 1
video_frame_counter = 0
while cap_cam.isOpened():
img = cv2.imread('photos' + sep + 'lutfen.jpg')
#BURADA OK VİDEOSU OYNATILACAK
#if not decetiona diye dene yarın.
blob = cv2.dnn.blobFromImage(img, 1 / 255, (whT, whT), [0, 0, 0], 1, crop=False)
net.setInput(blob)
layersNames = net.getLayerNames()
outputNames = [(layersNames[i[0] - 1]) for i in net.getUnconnectedOutLayers()]
outputs = net.forward(outputNames)
findObjects(outputs,img)
cv2.imshow('Image', img)
# Video feed
if hey == 1:
filename = 'photos' + sep + 'Baslksz-3.mp4'
cap_vid = cv2.VideoCapture(filename)
if hey == 0:
filename = 'photos' + sep + 'vid2.mp4'
cap_vid = cv2.VideoCapture(filename)
print(hey)
ret, frame_vid = cap_vid.read()
#cap_cam.set(cv2.CAP_PROP_FRAME_WIDTH, 1920)
#cap_cam.set(cv2.CAP_PROP_FRAME_HEIGHT, 1080)
# Resize the camera frame to the size of the video
height = int(cap_vid.get(cv2.CAP_PROP_FRAME_HEIGHT))
width = int(cap_vid.get(cv2.CAP_PROP_FRAME_WIDTH))
# Capture the next frame from camera
ret, frame_cam = cap_cam.read()
video_frame_counter += 1
if video_frame_counter == cap_vid.get(cv2.CAP_PROP_FRAME_COUNT):
video_frame_counter = 0
cap_vid.set(cv2.CAP_PROP_POS_FRAMES, 0)
frame_cam = cv2.resize(frame_cam, (width, height), interpolation = cv2.INTER_AREA)
#ret = cap_vid.set(cv2.CAP_PROP_POS_MSEC, time_passed)
ret, frame_vid = cap_vid.read()
if not ret:
print('Cannot read from video stream')
break
# Blend the two images and show the result
tr = 0.4 # transparency between 0-1, show camera if 0
frame = ((1-tr) * frame_cam.astype(np.float) + tr * frame_vid.astype(np.float)).astype(np.uint8)
cv2.imshow('Transparent result', frame)
if cv2.waitKey(1) == 27: # ESC is pressed
break
cap_cam.release()
cap_vid.release()
cv2.destroyAllWindows()
The easy way
You can use the cv.arrowedLine() function that will draw something similar to what you want. For example, to draw a red arrow above your rectangle:
center_x = x + w//2
cv2.arrowedLine(img, (center_x, y-50), (center_x, y-5), (0,0,255), 2, 8, 0, 0.5)
which should give a result similar to the image below. Take a look at the OpenCV documentation for the description of the parameters of the function. You can change its size, thickness, color, etc.
Custom arrow shape
If you want more control over the shape of your arrow, you can define a contour (vertex by vertex) and use cv.drawContours() to render it. For example:
# define the arrow shape
shape = np.array([[[0,0],[-25,-25],[-10,-25],[-10,-50],
[10,-50],[10,-25],[25,-25]]])
# move it to the desired position
cx = x + w // 2
cy = y - 5
shape[:,:,0] += cx
shape[:,:,1] += cy
# draw it
cv2.drawContours(img, shape, -1, (0, 255, 0), -1)
This snippet will give you the image below. You can adjust the shape by altering the vertices in the shape array, or look at the documentation to change the way OpenCV draws it.
Hi I am trying to make the eyes that is circled to be white. I know we cant delete the eyes so i wanted to mask it, but i couldnt figure out a way. Below is my code.
import cv2
import os
cascPathface = os.path.dirname(
cv2.__file__) + "/data/haarcascade_frontalface_alt2.xml"
cascPatheyes = os.path.dirname(
cv2.__file__) + "/data/haarcascade_eye_tree_eyeglasses.xml"
faceCascade = cv2.CascadeClassifier(cascPathface)
eyeCascade = cv2.CascadeClassifier(cascPatheyes)
while True:
img = cv2.imread('man1.png')
newImg = cv2.resize(img, (600,600))
gray = cv2.cvtColor(newImg, cv2.COLOR_BGR2GRAY)
faces = faceCascade.detectMultiScale(gray,
scaleFactor=1.1,
minNeighbors=5,
minSize=(60, 60),
flags=cv2.CASCADE_SCALE_IMAGE)
for (x,y,w,h) in faces:
cv2.rectangle(newImg, (x, y), (x + w, y + h),(0,255,0), 2)
faceROI = newImg[y:y+h,x:x+w]
eyes = eyeCascade.detectMultiScale(faceROI)
for (x2, y2, w2, h2) in eyes:
eye_center = (x + x2 + w2 // 2, y + y2 + h2 // 2)
radius = int(round((w2 + h2) * 0.25))
frame = cv2.circle(newImg, eye_center, radius, (255, 0, 0), 4)
# Display the resulting frame
cv2.imshow('Image', newImg)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
last = cv2.imwrite('faces_detected.png', faceROI)
cv2.destroyAllWindows()
This is the image where i want the eyes to be white:
In order to mask the eyes, change the thickness parameter in the cv2.circle method to -1. That will fill the circle with the specified color.
Change the code from frame = cv2.circle(newImg, eye_center, radius, (255, 0, 0), 4) to frame = cv2.circle(newImg, eye_center, radius, (255, 0, 0), -1).
Refer: https://www.geeksforgeeks.org/python-opencv-cv2-circle-method/
Kindly do upvote the solution, if you find it helpful.
I have been using PIL Image
I am trying to draw text on an image. I want this text to have a black outline like most memes. I've attempted to do this by drawing a shadow letter of a bigger font behind the letter in front. I've adjusted the x and y postions of the shadow accordingly. The shadow is slightly off though. The letter in front should be exactly in the middle of the shadow letter, but this isn't the case. The question mark certainly isn't centered horizontally, and all the letters are too low vertically. The outline also just doesn't look good.
Below is a minimum reproducible example to produce the image above.
Link to the font
Link to original image
from PIL import Image, ImageDraw, ImageFont
caption = "Why is the text slightly off?"
img = Image.open('./example-img.jpg')
d = ImageDraw.Draw(img)
x, y = 10, 400
font = ImageFont.truetype(font='./impact.ttf', size=50)
shadowFont = ImageFont.truetype(font='./impact.ttf', size=60)
for idx in range(0, len(caption)):
char = caption[idx]
w, h = font.getsize(char)
sw, sh = shadowFont.getsize(char) # shadow width, shadow height
sx = x - ((sw - w) / 2) # Shadow x
sy = y - ((sh - h) / 2) # Shadow y
# print(x,y,sx,sy,w,h,sw,sh)
d.text((sx, sy), char, fill="black", font=shadowFont) # Drawing the text
d.text((x, y), char, fill=(255,255,255), font=font) # Drawing the text
x += w + 5
img.save('example-output.jpg')
Another approach includes drawing the text 4 times in black behind the main text at positions slightly higher, slightly lower, slightly left, and slightly right, but these have also not been optimal as shown below
Code to produce the image above
from PIL import Image, ImageDraw, ImageFont
caption = "Why does the Y and i look weird?"
x, y = 10, 400
font = ImageFont.truetype(font='./impact.ttf', size=60)
img = Image.open('./example-img.jpg')
d = ImageDraw.Draw(img)
shadowColor = (0, 0, 0)
thickness = 4
d.text((x - thickness, y - thickness), caption, font=font, fill=shadowColor, thick=thickness)
d.text((x + thickness, y - thickness), caption, font=font, fill=shadowColor, thick=thickness)
d.text((x - thickness, y + thickness), caption, font=font, fill=shadowColor, thick=thickness)
d.text((x + thickness, y + thickness), caption, font=font, fill=shadowColor, thick=thickness)
d.text((x, y), caption, spacing=4, fill=(255, 255, 255), font=font) # Drawing the text
img.save('example-output.jpg')
I don't know since what version, but about a year ago Pillow added text stroking. You probably need to update it if you haven't do so lately. Example usage with stroke_width of 2:
from PIL import Image, ImageDraw, ImageFont
caption = 'I need to update my Pillow'
img = Image.open('./example-img.jpg')
d = ImageDraw.Draw(img)
font = ImageFont.truetype('impact.ttf', size=50)
d.text((10, 400), caption, fill='white', font=font,
stroke_width=2, stroke_fill='black')
img.save('example-output.jpg')
You can use mathlibplot text Stroke effect which uses PIL.
Example:
import matplotlib.pyplot as plt
import matplotlib.patheffects as path_effects
import matplotlib.image as mpimg
fig = plt.figure(figsize=(7, 5))
fig.figimage(mpimg.imread('seal.jpg'))
text = fig.text(0.5, 0.1, 'This text stands out because of\n'
'its black border.', color='white',
ha='center', va='center', size=30)
text.set_path_effects([path_effects.Stroke(linewidth=3, foreground='black'),
path_effects.Normal()])
plt.savefig('meme.png')
Result:
As #Abang pointed out, use stroke_width and stroke_fill.
Link for more details
Code:
from PIL import Image, ImageDraw, ImageFont
caption = 'Ans: stroke_width & stroke_fill'
img = Image.open('./example-img.jpg')
d = ImageDraw.Draw(img)
font = ImageFont.truetype('impact.ttf', size=50)
d.text((60, 400), caption, fill='white', font=font, spacing = 4, align = 'center',
stroke_width=4, stroke_fill='black')
img.save('example-output.jpg')
I am trying to generate the CLEVR dataset with some random images of rectangles and circle. When I am debugging the code for every plt.imshow() statement I can see a new image with the shape generated alongwith the shapes generated in the last executed loops. Although, to my surprise everytime the 5th image generated never shows during the debugging mode.
Also when I save the images locally I see only two objects. Please find the images for reference purposes.
import matplotlib.pyplot as plt
import cv2
import numpy as np
colors = [
(0, 0, 255), # r
(0, 255, 0), # g
(255, 0, 0), # b
(0, 156, 255), # o
(128, 128, 128), # k
(0, 255, 255) # y
]
img_size = 75
size = 5
def center_generate(objects):
while True:
pas = True
center = np.random.randint(0+size, img_size - size, 2)
if len(objects) > 0:
for name, c, shape in objects:
"""this condition checks if the new object generated is not completely covered by the already
generated objects"""
if ((center - c) ** 2).sum() < ((size * 2) ** 2):
pas = False
if pas:
return center
def build_dataset(dataset_type, loopnumber):
objects = []
img = np.ones((img_size, img_size, 3)) * 255
for color_id, color in enumerate(colors):
center = center_generate(objects)
if random.random() < 0.5:
start = (center[0]-size, center[1]-size)
end = (center[0]+size, center[1]+size)
img = cv2.rectangle(img, start, end, color, -1)
plt.imshow(img)
objects.append((color_id, center, 'r'))
else:
center_ = (center[0], center[1])
img = cv2.circle(img, center_, size, color, -1)
plt.imshow(img)
objects.append((color_id, center, 'c'))
if dataset_type == 'test':
plt.imsave('..\\img\\test\\img_' + str(loop) + '.jpeg', img)
else:
plt.imsave('..\\img\\train\\img_' + str(loop) + '.jpeg', img)
The image generated during debugging.
Image stored locally.
Could anyone explain the issue here?
Thanks
To save the image use cv2.imwrite():
cv2.imwrite('..\\img\\train\\img_' + str(loop) + '.jpeg', img)
Also to correctly save it with plt.imsave, you need to divide by 255:
plt.imsave('..\\img\\train\\img_' + str(loop) + '.jpeg', img/255.0)
or convert them to 'uint8':
img = img.astype('uint8')
plt.imsave('..\\img\\train\\img_' + str(loop) + '.jpeg', img)