Related
I have a project for face recognition in Python, but when I try to open the camera for recognition, it does not open. May be there is something wrong in my code, but I do not know where the problem is.
its the code app.py
maybe the wrong be in here def of facerecognition
`def face_recognition(): # generate frame by frame from camera
def draw_boundary(img, classifier, scaleFactor, minNeighbors, color, text, clf):
gray_image = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
features = classifier.detectMultiScale(gray_image, scaleFactor, minNeighbors)
global justscanned
global pause_cnt
pause_cnt += 1
coords = []
for (x, y, w, h) in features:
cv2.rectangle(img, (x, y), (x + w, y + h), color, 2)
id, pred = clf.predict(gray_image[y:y + h, x:x + w])
confidence = int(100 * (1 - pred / 300))
if confidence > 85 and not justscanned:
global cnt
cnt += 1
n = (100 / 30) * cnt
# w_filled = (n / 100) * w
w_filled = (cnt / 30) * w
cv2.putText(img, str(int(n))+' %', (x + 20, y + h + 28), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (153, 255, 255), 2, cv2.LINE_AA)
cv2.rectangle(img, (x, y + h + 40), (x + w, y + h + 50), color, 2)
cv2.rectangle(img, (x, y + h + 40), (x + int(w_filled), y + h + 50), (153, 255, 255), cv2.FILLED)
mycursor.execute("select a.img_person, b.prs_name, b.prs_skill "
" from img_dataset a "
" left join prs_mstr b on a.img_person = b.prs_nbr "
" where img_id = " + str(id))
row = mycursor.fetchone()
pnbr = row[0]
pname = row[1]
pskill = row[2]
if int(cnt) == 30:
cnt = 0
mycursor.execute("insert into accs_hist (accs_date, accs_prsn) values('"+str(date.today())+"', '" + pnbr + "')")
mydb.commit()
cv2.putText(img, pname + ' | ' + pskill, (x - 10, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (153, 255, 255), 2, cv2.LINE_AA)
time.sleep(1)
justscanned = True
pause_cnt = 0
else:
if not justscanned:
cv2.putText(img, 'UNKNOWN', (x, y - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 0, 255), 2, cv2.LINE_AA)
else:
cv2.putText(img, ' ', (x, y - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 0, 255), 2,cv2.LINE_AA)
if pause_cnt > 80:
justscanned = False
coords = [x, y, w, h]
return coords`
I have a problem.
I have an object detection model that detects two classes, what I want to do is:
Detect class 1 (say c1) on source image (640x640) Draw bounding box and crop bounding box -> (c1 image) and then resize it to (640x640) (DONE)
Detect class 2 (say c2) on c1 image (640x640) (DONE)
Now I want to draw bounding box of c2 on source image
I have tried to explain it here by visualizing it
how can I do it? please help.
Code:
frame = self.REC.ImgResize(frame)
frame, score1, self.FLAG1, x, y, w, h = self.Detect(frame, "c1")
if self.FLAG1 and x > 0 and y > 0:
x1, y1 = w,h
cv2.rectangle(frame, (x, y), (w, h), self.COLOR1, 1)
c1Img = frame[y:h, x:w]
c1Img = self.REC.ImgResize(c1Img)
ratio = c2Img.shape[1] / float(frame.shape[1])
if ratio > 0.35:
c2Img, score2, self.FLAG2, xN, yN, wN, hN = self.Detect(c1Img, "c2")
if self.FLAG2 and xN > 0 and yN > 0:
# What should be the values for these => (__, __),(__,__)
cv2.rectangle(frame, (__, __), (__, __), self.COLOR2, 1)
I had tried a way which could only solve (x,y) coordinates but width and height was a mess
what I tried was
first found the rate of width and height at which the cropped c1 image increased after resize.
for example
x1 = 329
y1 = 102
h1 = 637
w1 = 630
r_w = 630 / 640 # 0.9843
r_h = 637 / 640 # 0.9953
x2 = 158
y2 = 393
h2 = 499
w2 = 588
new_x2 = 158 * 0.9843 # 156
new_y2 = 389 * 0.9953 # 389
new_x2 = x1 + new_x2
new_y2 = y1 + new_y2
this work to find (x,y)
but I am still trying to find a way to get (w,h) of the bounding box.
EDIT
The complete code is:
import cv2
import random
import numpy as np
import onnxruntime as ort
cuda = False
w = "models/model.onnx"
providers = ['CUDAExecutionProvider', 'CPUExecutionProvider'] if cuda else ['CPUExecutionProvider']
session = ort.InferenceSession(w, providers=providers)
names = ['face', 'glasses']
colors = {name:[random.randint(0, 255) for _ in range(3)] for name in names}
img = cv2.imread("test.jpg")
def ImgResize(image, width = 640, height = 640, inter = cv2.INTER_CUBIC):
if image is not None:
resized = cv2.resize(image, (width,height), interpolation = inter)
return resized
def Detect(im, new_shape=(640, 640), color=(114, 114, 114), auto=True, scaleup=True, stride=32):
flag = False
w, h = 0, 0
x, y = 0, 0
score = 0
try:
if im is None:
raise Exception(IOError())
shape = im.shape[:2]
if isinstance(new_shape, int):
new_shape = (new_shape, new_shape)
ratio = min(new_shape[0] / shape[0], new_shape[1] / shape[1])
if not scaleup:
ratio = min(ratio, 1.0)
new_unpad = int(round(shape[1] * ratio)), int(round(shape[0] * ratio))
dw, dh = new_shape[1] - new_unpad[0], new_shape[0] - new_unpad[1]
if auto:
dw, dh = np.mod(dw, stride), np.mod(dh, stride)
dw /= 2
dh /= 2
if shape[::-1] != new_unpad:
im = cv2.resize(im, new_unpad, interpolation=cv2.INTER_LINEAR)
top, bottom = int(round(dh - 0.1)), int(round(dh + 0.1))
left, right = int(round(dw - 0.1)), int(round(dw + 0.1))
im = cv2.copyMakeBorder(im, top, bottom, left, right, cv2.BORDER_CONSTANT, value=color)
image_ = im.transpose((2, 0, 1))
image_ = np.expand_dims(image_, 0)
image_ = np.ascontiguousarray(image_)
im = image_.astype(np.float32)
im /= 255
outname = [i.name for i in session.get_outputs()]
inname = [i.name for i in session.get_inputs()]
inp = {inname[0]:im}
outputs = session.run(outname, inp)[0]
return im, outputs, ratio, (dw, dh)
except IOError:
print("Invalid Image File")
def Detection(img, c_name):
score = 0
name = ""
a, b, c, d = 0, 0, 0, 0
image_, outputs, ratio, dwdh = Detect(img)
ori_images = [img.copy()]
for batch_id, x0, y0, x1, y1, cls_id, score in outputs:
img = ori_images[int(batch_id)]
box = np.array([x0, y0, x1, y1])
box -= np.array(dwdh * 2)
box /= ratio
box = box.round().astype(np.int32).tolist()
cls_id = int(cls_id)
score = round(float(score), 3)
if score > 0.55:
name = names[cls_id]
if name != c_name:
return img, 0, False, 0, 0, 0, 0, "Could Not Detect"
flag = True
a, b, c, d = tuple(box)
score = round(score * 100, 0)
return img, score, flag, a, b, c, d, name
COLORF = (212, 15, 24)
COLORG = (25, 240, 255)
nameW = "Det"
flagF, flagN = False, False
img = ImgResize(img)
c1_img, score, flagF, x1,y1,w1,h1,name = Detection(img,"face")
print(score, flagF, x1,y1,w1,h1,name)
if flagF:
cv2.rectangle(img, (x1,y1), (w1,h1), COLORF, 1)
cv2.putText(img, name, (x1,y1),cv2.FONT_HERSHEY_PLAIN, 2,COLORF,2)
cv2.imshow("face", img)
c1_img = c1_img[y1:h1,x1:w1]
c1_img_orig = c1_img.copy()
c1_img = ImgResize(c1_img)
c2_img, score, flagG, x2,y2,w2,h2,name = Detection(c1_img,"glasses")
if flagG:
c2_img = c2_img[y2:h2,x2:w2]
cv2.rectangle(c1_img_orig, (x2,y2), (w2,h2), COLORG, 1)
cv2.putText(c1_img_orig, name, (x1,y1),cv2.FONT_HERSHEY_PLAIN, 2,COLORG,2)
cv2.imshow("glasses", c2_img)
x3 = x1 + int(x2 * w1 / 640)
y3 = y1 + int(y2 * h1 / 640)
w3 = int(w2 * w1 / 640)
h3 = int(h2 * h1 / 640)
cv2.rectangle(img, (x3,y3), (w3,h3), COLORG, 1)
cv2.imshow(nameW, img)
cv2.waitKey(0)
cv2.destroyAllWindows()
what this code does is for some images it draws the bounding box as required:
but for other images and in video stream this is what happens:
Here is a complete programming example. Please keep in mind that for cv2.rectangle you need to pass top-left corner and bottom-right corner of the rectangle. As you didn't share ImgResize and Detect I made some assumptions:
import cv2
import numpy as np
COLOR1 = (0, 255, 0)
COLOR2 = (0, 0, 255)
DETECT_c1 = (40, 20, 120, 160)
DETECT_c2 = (20, 120, 160, 40)
RESIZE_x, RESIZE_y = 200, 200
frame = np.zeros((RESIZE_y, RESIZE_x, 3), np.uint8)
x1, y1, w1, h1 = DETECT_c1
c1Img = frame[y1:h1, x1:w1]
cv2.rectangle(frame, (x1, y1), (x1 + w1, y1 + h1), COLOR1, 1)
c1Img = cv2.resize(c1Img, (RESIZE_x, RESIZE_y))
x2, y2, w2, h2 = DETECT_c2
x3 = x1 + int(x2 * w1 / RESIZE_x)
y3 = y1 + int(y2 * h1 / RESIZE_y)
w3 = int(w2 * w1 / RESIZE_x)
h3 = int(h2 * h1 / RESIZE_y)
cv2.rectangle(frame, (x3, y3), (x3 + w3, y3 + h3), COLOR2, 1)
cv2.imwrite('out.png', frame)
Output:
I suggest that you treat your bounding box coordinates relatively.
If I understand correctly, your problem is that you have different referential. One way to bypass that is to normalize at each step your bbox coordinates.
c1_box is relative to your image, so :
c1_x = x/640
c1_y = y/640
When you crop, you can record the ratio values between main image and your cropped object.
image_vs_c1_x = c1_x / img_x
image_vs_c1_y = c1_y / img_y
Then you need to multiply your c2 bounding box coordinates by those ratios.
this is how I was able to solve it.
rwf = round((w1-x1)/640, 2)
rhf = round((h1-y1)/640, 2)
x3 = int(x2*rwf )
y3 = int(y2*rhf)
w3 = int(w2*rwf)
h3 = int(h2*rhf)
# these are the top right and bottom left cooridinates
x4 = x1 + x3
y4 = y1 + y3
w4 = x1 + w3
h4 = y1 + h3
I am making a very basic 3d engine. When I render 2 or more objects, it draws lines between them. I do not know why this happens, as I coded the pen to go up after drawing every triangle. A strange thing is that when I draw a background line, each object also draws lines to the background line. I am confused. There is only 1 reason I could think of; it uses the last point of the other object as the first point of the first triangle of the main object. However, it does not seem like this is the case, as it is even happening with a simple line in the background as well.
from turtle import*
from time import*
from math import*
wn=Screen()
speed(0)
ht()
pu()
wn.tracer(0,0)
fov=200
camx=0
camy=0
camz=-5
xoff=0
yoff=0
zoff=0
xrot=pi*2
yrot=pi
zrot=pi
def goto3d(x,y,z):
rotxx=x
rotxy=y*cos(yrot)-z*sin(yrot)
rotxz=y*sin(yrot)+z*cos(yrot)
rotyx=rotxx*cos(xrot)+rotxz*sin(xrot)
rotyy=rotxy
rotyz=rotxz*cos(xrot)-rotxx*sin(xrot)
rotzx=rotyx*cos(zrot)-rotyy*sin(zrot)
rotzy=rotyx*sin(zrot)+rotyy*cos(zrot)
rotzz=rotyz
transx=rotzx-xoff
transy=rotzy-yoff
transz=rotzz-zoff
newx=fov*transx/transz
newy=fov*transy/transz
if transz<0.1 or newx<=-200 or newy<=-200 or newx>=200 or newy>=200:
return
goto(newx,newy)
def triangle(p1x,p1y,p1z,p2x,p2y,p2z,p3x,p3y,p3z):
goto3d(p1x,p1y,p1z)
pd()
goto3d(p2x,p2y,p2z)
goto3d(p3x,p3y,p3z)
goto3d(p1x,p1y,p1z)
pu()
def face(p1x,p1y,p1z,p2x,p2y,p2z,p3x,p3y,p3z,p4x,p4y,p4z,r,g,b,a):
fillcolor(r,g,b,a)
begin_fill()
triangle(p1x,p1y,p1z,p2x,p2y,p2z,p3x,p3y,p3z)
end_fill()
begin_fill()
triangle(p2x,p2y,p2z,p3x,p3y,p3z,p4x,p4y,p4z)
end_fill()
def bbox(x,y,z,w,h,l,r,g,b,a):
x+=camx
y+=camy
z+=camz
face(x+-w,y+h,z+l,x+w,y+h,z+l,x+-w,y+-h,z+l,x+w,y+-h,z+l,r,g,b,a)
face(x+-w,y+h,z+-l,x+w,y+h,z+-l,x+-w,y+-h,z+-l,x+w,y+-h,z+-l,r,g,b,a)
face(x+-w,y+h,z+l,x+-w,y+h,z+-l,x+-w,y+-h,z+l,x+-w,y+-h,z+-l,r,g,b,a)
face(x+w,y+h,z+l,x+w,y+h,z+-l,x+w,y+-h,z+l,x+w,y+-h,z+-l,r,g,b,a)
face(x+-w,y+-h,z+l,x+-w,y+-h,z+-l,x+w,y+-h,z+l,x+w,y+-h,z+-l,r,g,b,a)
face(x+-w,y+h,z+l,x+-w,y+h,z+-l,x+w,y+h,z+l,x+w,y+h,z+-l,r,g,b,a)
def box(x,y,z,w,h,l,r,g,b):
if w>=2 or h>=2 or l>=2:
bbox(x-(w/4),y-(h/4),z-(l/4),w/4,h/4,l/4,r,g,b,.2)
bbox(x+(w/4),y-(h/4),z-(l/4),w/4,h/4,l/4,r,g,b,.2)
bbox(x+(w/4),y+(h/4),z-(l/4),w/4,h/4,l/4,r,g,b,.2)
bbox(x-(w/4),y+(h/4),z-(l/4),w/4,h/4,l/4,r,g,b,.2)
bbox(x-(w/4),y-(h/4),z+(l/4),w/4,h/4,l/4,r,g,b,.2)
bbox(x+(w/4),y-(h/4),z+(l/4),w/4,h/4,l/4,r,g,b,.2)
bbox(x+(w/4),y+(h/4),z+(l/4),w/4,h/4,l/4,r,g,b,.2)
bbox(x-(w/4),y+(h/4),z+(l/4),w/4,h/4,l/4,r,g,b,.2)
else:
bbox(x,y,z,w,h,l,r,g,b,.5)
def render():
goto(-200,-5)
pd()
goto(200,-5)
pu()
### ||| objects go here ||| ###
### ||| format is box(x,y,z,width,height,length,r,g,b) ||| ###
box(2,0,-5,2,2,2,0,255,255)
box(0,0,0,1,1,1,255,0,0)
def tl():
global xrot
xrot-=pi/40
def tr():
global xrot
xrot+=pi/40
def f():
global camx
global camz
camz+=.3*cos(-xrot)
camx+=-(.3*sin(-xrot))
def b():
global camx
global camz
camz+=-(.3*cos(-xrot))
camx+=.3*sin(-xrot)
wn.onkey(tl,'Left')
wn.onkey(tr,'Right')
wn.onkey(f,'Up')
wn.onkey(b,'Down')
wn.listen()
while True:
clear()
render()
update()
When I render 2 or more objects, it draws lines between them. I do not
know why this happens
The problem happens even when you only have one object -- comment out your first (small blue) box and just move the second (large red) one:
The problem is in goto3d() and triangle() as goto3d() has a failure situation (which it tests for) that it doesn't signal back to triangle() so it goes ahead and continues drawing.
Below is my rework of your code to patch this issue (and translate the code into Python ;-)
from turtle import Screen, Turtle
from math import pi, sin, cos
fov = 200
camx = 0
camy = 0
camz = -5
xoff = 0
yoff = 0
zoff = 0
xrot = pi * 2
yrot = pi
zrot = pi
def goto3d(x, y, z):
rotxx = x
rotxy = y * cos(yrot) - z * sin(yrot)
rotxz = y * sin(yrot) + z * cos(yrot)
rotyx = rotxx * cos(xrot) + rotxz * sin(xrot)
rotyy = rotxy
rotyz = rotxz * cos(xrot) - rotxx * sin(xrot)
rotzx = rotyx * cos(zrot) - rotyy * sin(zrot)
rotzy = rotyx * sin(zrot) + rotyy * cos(zrot)
rotzz = rotyz
transx = rotzx - xoff
transy = rotzy - yoff
transz = rotzz - zoff
if transz < 0.1:
return False
newx = fov * transx/transz
newy = fov * transy/transz
if not -200 < newx < 200 or not -200 < newy < 200:
return False
turtle.goto(newx, newy)
return True
def triangle(p1x, p1y, p1z, p2x, p2y, p2z, p3x, p3y, p3z):
if goto3d(p1x, p1y, p1z):
turtle.pendown()
turtle.begin_fill()
goto3d(p2x, p2y, p2z)
goto3d(p3x, p3y, p3z)
goto3d(p1x, p1y, p1z)
turtle.end_fill()
turtle.penup()
def face(p1x, p1y, p1z, p2x, p2y, p2z, p3x, p3y, p3z, p4x, p4y, p4z, color):
turtle.fillcolor(color)
triangle(p1x, p1y, p1z, p2x, p2y, p2z, p3x, p3y, p3z)
triangle(p2x, p2y, p2z, p3x, p3y, p3z, p4x, p4y, p4z)
def bbox(x, y, z, w, h, l, color):
x += camx
y += camy
z += camz
face(x - w, y + h, z + l, x + w, y + h, z + l, x - w, y - h, z + l, x + w, y - h, z + l, color)
face(x - w, y + h, z - l, x + w, y + h, z - l, x - w, y - h, z - l, x + w, y - h, z - l, color)
face(x - w, y + h, z + l, x - w, y + h, z - l, x - w, y - h, z + l, x - w, y - h, z - l, color)
face(x + w, y + h, z + l, x + w, y + h, z - l, x + w, y - h, z + l, x + w, y - h, z - l, color)
face(x - w, y - h, z + l, x - w, y - h, z - l, x + w, y - h, z + l, x + w, y - h, z - l, color)
face(x - w, y + h, z + l, x - w, y + h, z - l, x + w, y + h, z + l, x + w, y + h, z - l, color)
def box(x, y, z, w, h, l, color):
if w >= 2 or h >= 2 or l >= 2:
# transparent_color = (*color, 0.2)
transparent_color = color
bbox(x - w/4, y - h/4, z - l/4, w/4, h/4, l/4, transparent_color)
bbox(x + w/4, y - h/4, z - l/4, w/4, h/4, l/4, transparent_color)
bbox(x + w/4, y + h/4, z - l/4, w/4, h/4, l/4, transparent_color)
bbox(x - w/4, y + h/4, z - l/4, w/4, h/4, l/4, transparent_color)
bbox(x - w/4, y - h/4, z + l/4, w/4, h/4, l/4, transparent_color)
bbox(x + w/4, y - h/4, z + l/4, w/4, h/4, l/4, transparent_color)
bbox(x + w/4, y + h/4, z + l/4, w/4, h/4, l/4, transparent_color)
bbox(x - w/4, y + h/4, z + l/4, w/4, h/4, l/4, transparent_color)
else:
# transparent_color = (*color, 0.5)
transparent_color = color
bbox(x, y, z, w, h, l, transparent_color)
def render():
turtle.clear()
turtle.goto(-200, -5)
turtle.pendown()
turtle.goto(200, -5)
turtle.penup()
### ||| objects go here ||| ###
### ||| format is box(x, y, z, width, height, length, (r, g, b)) ||| ###
box(2, 0, -5, 2, 2, 2, (0, 255, 255))
box(0, 0, 0, 1, 1, 1, (255, 0, 0))
screen.update()
screen.ontimer(render)
def tl():
global xrot
xrot -= pi/40
def tr():
global xrot
xrot += pi/40
def f():
global camx, camz
camz += 0.3 * cos(-xrot)
camx += -(0.3 * sin(-xrot))
def b():
global camx, camz
camz += -(0.3 * cos(-xrot))
camx += 0.3 * sin(-xrot)
screen = Screen()
screen.tracer(0)
screen.colormode(255)
turtle = Turtle()
turtle.hideturtle()
turtle.penup()
screen.onkey(tl, 'Left')
screen.onkey(tr, 'Right')
screen.onkey(f, 'Up')
screen.onkey(b, 'Down')
screen.listen()
render()
screen.mainloop()
I disabled transparency as my system doesn't support it, but you can uncomment the appropriate lines to put it back.
I'm comparitively new to using CSV functions in python and need your help.
I have a python program that calculates distance between contours in opencv as well as angle, and this data is later stored in CSV file each time I press h on keyboard. The issue is that, each time I press h, the earlier line gets overwritten by the new line instead of saving it in new line. Is there any way I can save the new variable in new line in CSV format?
Here's part of my code. The whole code is long, so posting necessary part from it-
def calcDistHex(x6, y6, x5, y5, x4, y4, x3, y3, x2, y2, x, y):
dist1 = round(dist.euclidean((x6, y6), (x5, y5)))
dist2 = round(dist.euclidean((x5, y5), (x4, y4)))
dist3 = round(dist.euclidean((x4, y4), (x3, y3)))
dist4 = round(dist.euclidean((x3, y3), (x2, y2)))
dist5 = round(dist.euclidean((x2, y2), (x, y)))
dist6 = round(dist.euclidean((x, y), (x6, y6)))
#print(dist1)
cv2.putText(frame, str(dist1), (round(0.5 * x6 + 0.5 * x5), round(0.5 * y6 + 0.5 * y5)) , font, 0.5, (0, 0, 0), 1)
cv2.putText(frame, str(dist2), (round(0.5 * x5 + 0.5 * x4), round(0.5 * y5 + 0.5 * y4)) , font, 0.5, (0, 0, 0), 1)
cv2.putText(frame, str(dist3), (round(0.5 * x4 + 0.5 * x3), round(0.5 * y4 + 0.5 * y3)) , font, 0.5, (0, 0, 0), 1)
cv2.putText(frame, str(dist4), (round(0.5 * x3 + 0.5 * x2), round(0.5 * y3 + 0.5 * y2)) , font, 0.5, (0, 0, 0), 1)
cv2.putText(frame, str(dist5), (round(0.5 * x2 + 0.5 * x), round(0.5 * y2 + 0.5 * y)) , font, 0.5, (0, 0, 0), 1)
cv2.putText(frame, str(dist6), (round(0.5 * x + 0.5 * x6), round(0.5 * y + 0.5 * y6)) , font, 0.5, (0, 0, 0), 1)
pt6 = x6, y6
pt5 = x5, y5
pt4 = x4, y4
pt3 = x3, y3
pt2 = x2, y2
pt1 = x, y
m2 = gradient(pt2,pt1)
n2 = gradient(pt2,pt3)
if m2 is not None and n2 is not None:
angR2 = math.atan((n2-m2)/(1+(n2*m2)))
angD2 = math.degrees(angR2)
if math.isnan(angD2) is False:
cv2.putText(frame, str(round(abs(angD2))), (pt2[0]-40,pt2[1]-20), font, 1, (0, 0, 0))
#print(round(abs(angD2)),(pt1[0]-40,pt1[1]-20))
m3 = gradient(pt3,pt2)
n3 = gradient(pt3,pt4)
if m3 is not None and n3 is not None:
angR3 = math.atan((n3-m3)/(1+(n3*m3)))
angD3 = math.degrees(angR3)
if math.isnan(angD3) is False:
cv2.putText(frame, str(round(abs(angD3))), (pt3[0]-40,pt3[1]-20), font, 1, (0, 0, 0))
#print(round(abs(angD3)),(pt1[0]-40,pt1[1]-20))
m4 = gradient(pt4,pt3)
n4 = gradient(pt4,pt5)
if m4 is not None and n4 is not None:
angR4 = math.atan((n4-m4)/(1+(n4*m4)))
angD4 = math.degrees(angR4)
if math.isnan(angD4) is False:
cv2.putText(frame, str(round(abs(angD4))), (pt4[0]-40,pt4[1]-20), font, 1, (0, 0, 0))
#print(round(abs(angD4)),(pt1[0]-40,pt1[1]-20))
m5 = gradient(pt5,pt4)
n5 = gradient(pt5,pt6)
if m5 is not None and n5 is not None:
angR5 = math.atan((n5-m5)/(1+(n5*m5)))
angD5 = math.degrees(angR5)
if math.isnan(angD5) is False:
cv2.putText(frame, str(round(abs(angD5))), (pt5[0]-40,pt5[1]-20), font, 1, (0, 0, 0))
#print(round(abs(angD5)),(pt1[0]-40,pt1[1]-20))
m6 = gradient(pt6,pt5)
n6 = gradient(pt6,pt1)
if m6 is not None and n6 is not None:
angR6 = math.atan((n6-m6)/(1+(n6*m6)))
angD6 = math.degrees(angR6)
if math.isnan(angD6) is False:
cv2.putText(frame, str(round(abs(angD6))), (pt6[0]-40,pt6[1]-20), font, 1, (0, 0, 0))
#print(round(abs(angD6)),(pt1[0]-40,pt1[1]-20))
m = gradient(pt1,pt6)
n = gradient(pt1,pt2)
if m is not None and n is not None:
angR = math.atan((n-m)/(1+(n*m)))
angD = math.degrees(angR)
if math.isnan(angD) is False:
cv2.putText(frame, str(round(abs(angD))), (pt1[0]-40,pt1[1]-20), font, 1, (0, 0, 0))
#print(round(abs(angD)),(pt1[0]-40,pt1[1]-20))
if cv2.waitKey(1) == ord('h'):
timestamp = int(time.time() * 10000)
with open('dataset.csv', 'w', newline='') as dataset_file:
dataset = csv.DictWriter(
dataset_file,
["timestamp", "shape", "Side1", "Side2", "Side3", "Side4", "Side5", "Side6", "Perimeter", "Angle1", "Angle2", "Angle3", "Angle4", "Angle5", "Angle6", "AngleSum", "Error"]
)
dataset.writeheader()
dataset.writerow({
"timestamp": timestamp,
"shape": "Hexagon",
"Side1": dist1,
"Side2": dist2,
"Side3": dist3,
"Side4": dist4,
"Side5": dist5,
"Side6": dist6,
"Perimeter": (dist1 + dist2 + dist3 + dist4 + dist5 + dist6),
"Angle1": angD,
"Angle2": angD2,
"Angle3": angD3,
"Angle4": angD4,
"Angle5": angD5,
"Angle6": angD6,
"AngleSum": (angD + angD2 + angD3 + angD4 + angD5 + angD6),
"Error": "To Do"
})
return dist1, dist2, dist3, dist4, dist5, dist6, angD, angD2, angD3, angD4, angD5, angD6;
This is the defined function which stores the file.
This function is later called in another loop -
if len(approx) == 6:
for j in n:
if(i % 2 == 0):
x6 = n[i - 10]
y6 = n[i - 9]
x5 = n[i - 8]
y5 = n[i - 7]
x4 = n[i - 6]
y4 = n[i - 5]
x3 = n[i - 4]
y3 = n[i - 3]
x2 = n[i - 2]
y2 = n[i - 1]
x = n[i]
y = n[i + 1]
#print(x, y, x2, y2, x3, y3, x4, y4)
string = str(x) + " " + str(y)
cv2.circle(frame, (x, y), 2, (0,0,100), 2)
cv2.putText(frame, string, (x, y), font, 0.5, (138, 138, 54), 2)
calcDistHex(x6, y6, x5, y5, x4, y4, x3, y3, x2, y2, x, y)
# text on remaining co-ordinates.
i = i + 1
cv2.imshow("Frame", frame)
cv2.imshow("Mask", threshold)
Any help is appreciated. Written in python.
Try changing this line :
with open('dataset.csv', 'w', newline='') as dataset_file:
By :
with open('dataset.csv', 'a', newline='') as dataset_file:
The 'w' means overwrite. The 'a' means append. More info here : https://stackoverflow.com/a/1466036/3922534
Edit : to avoid the duplicated header at each write, delete the line :
dataset.writeheader()
from your current code, and add the following code before your program's loop. It will itinialize the file by overriding it with the CSV header (notice the 'w' mode), then the loop inside your program will only add the rows of data.
with open('dataset.csv', 'w', newline='') as dataset_file:
dataset = csv.DictWriter(
dataset_file,
["timestamp", "shape", "Side1", "Side2", "Side3", "Side4", "Side5", "Side6", "Perimeter", "Angle1", "Angle2", "Angle3", "Angle4", "Angle5", "Angle6", "AngleSum", "Error"]
)
dataset.writeheader()
In Android, I used the following code to generate a gradient background that I need:
<gradient
android:angle="90"
android:startColor="#40000000"
android:endColor="#00000000"
android:type="linear" />
The background goes from light to relatively dark from top to bottom. I wonder how to do the same in Python with PIL, since I need the same effect on another program written in Python.
Here's something that shows ways to draw multicolor rectangular horizontal and vertical gradients.
rom PIL import Image, ImageDraw
BLACK, DARKGRAY, GRAY = ((0,0,0), (63,63,63), (127,127,127))
LIGHTGRAY, WHITE = ((191,191,191), (255,255,255))
BLUE, GREEN, RED = ((0, 0, 255), (0, 255, 0), (255, 0, 0))
class Point(object):
def __init__(self, x, y):
self.x, self.y = x, y
class Rect(object):
def __init__(self, x1, y1, x2, y2):
minx, maxx = (x1,x2) if x1 < x2 else (x2,x1)
miny, maxy = (y1,y2) if y1 < y2 else (y2,y1)
self.min = Point(minx, miny)
self.max = Point(maxx, maxy)
width = property(lambda self: self.max.x - self.min.x)
height = property(lambda self: self.max.y - self.min.y)
def gradient_color(minval, maxval, val, color_palette):
""" Computes intermediate RGB color of a value in the range of minval
to maxval (inclusive) based on a color_palette representing the range.
"""
max_index = len(color_palette)-1
delta = maxval - minval
if delta == 0:
delta = 1
v = float(val-minval) / delta * max_index
i1, i2 = int(v), min(int(v)+1, max_index)
(r1, g1, b1), (r2, g2, b2) = color_palette[i1], color_palette[i2]
f = v - i1
return int(r1 + f*(r2-r1)), int(g1 + f*(g2-g1)), int(b1 + f*(b2-b1))
def horz_gradient(draw, rect, color_func, color_palette):
minval, maxval = 1, len(color_palette)
delta = maxval - minval
width = float(rect.width) # Cache.
for x in range(rect.min.x, rect.max.x+1):
f = (x - rect.min.x) / width
val = minval + f * delta
color = color_func(minval, maxval, val, color_palette)
draw.line([(x, rect.min.y), (x, rect.max.y)], fill=color)
def vert_gradient(draw, rect, color_func, color_palette):
minval, maxval = 1, len(color_palette)
delta = maxval - minval
height = float(rect.height) # Cache.
for y in range(rect.min.y, rect.max.y+1):
f = (y - rect.min.y) / height
val = minval + f * delta
color = color_func(minval, maxval, val, color_palette)
draw.line([(rect.min.x, y), (rect.max.x, y)], fill=color)
if __name__ == '__main__':
# Draw a three color vertical gradient.
color_palette = [BLUE, GREEN, RED]
region = Rect(0, 0, 730, 350)
width, height = region.max.x+1, region.max.y+1
image = Image.new("RGB", (width, height), WHITE)
draw = ImageDraw.Draw(image)
vert_gradient(draw, region, gradient_color, color_palette)
image.show()
#image.save("vert_gradient.png", "PNG")
#print('image saved')
And here's the image it generates and displays:
This calculates the intermediate colors in the RGB color space, but other colorspaces could be used — for examples compare results of my answers to the question Range values to pseudocolor.
This could easily be extended to generate RGBA (RGB+Alpha) mode images.
If you only need two colours, this can be done very simply:
def generate_gradient(
colour1: str, colour2: str, width: int, height: int) -> Image:
"""Generate a vertical gradient."""
base = Image.new('RGB', (width, height), colour1)
top = Image.new('RGB', (width, height), colour2)
mask = Image.new('L', (width, height))
mask_data = []
for y in range(height):
mask_data.extend([int(255 * (y / height))] * width)
mask.putdata(mask_data)
base.paste(top, (0, 0), mask)
return base
This creates a layer in each colour, then creates a mask with transparency varying according to the y position. You can replace y / height in line 10 with x / width for a horizontal gradient, or any function of x and y for another gradient.
Here is the technique spelled out. You need 2 layers on top of each other, one for each color. Then you make the transparency for each increasing for the top layer and decreasing for the bottom layer. For extra homework you can change the rate of transparency to an ascending logarithmic scale rather than linear. Have fun with it.
Making some modifications to #martineau's code, this function handles gradient orientation in degrees (not only vertical or horizontal):
from PIL import Image
import math
BLACK, DARKGRAY, GRAY = ((0,0,0), (63,63,63), (127,127,127))
LIGHTGRAY, WHITE = ((191,191,191), (255,255,255))
BLUE, GREEN, RED = ((0, 0, 255), (0, 255, 0), (255, 0, 0))
class Point(object):
def __init__(self, x, y):
self.x, self.y = x, y
def rot_x(self, degrees):
radians = math.radians(degrees)
return self.x * math.cos(radians) + self.y * math.sin(radians)
class Rect(object):
def __init__(self, x1, y1, x2, y2):
minx, maxx = (x1,x2) if x1 < x2 else (x2,x1)
miny, maxy = (y1,y2) if y1 < y2 else (y2,y1)
self.min = Point(minx, miny)
self.max = Point(maxx, maxy)
def min_max_rot_x(self, degrees):
first = True
for x in [self.min.x, self.max.x]:
for y in [self.min.y, self.max.y]:
p = Point(x, y)
rot_d = p.rot_x(degrees)
if first:
min_d = rot_d
max_d = rot_d
else:
min_d = min(min_d, rot_d)
max_d = max(max_d, rot_d)
first = False
return min_d, max_d
width = property(lambda self: self.max.x - self.min.x)
height = property(lambda self: self.max.y - self.min.y)
def gradient_color(minval, maxval, val, color_palette):
""" Computes intermediate RGB color of a value in the range of minval
to maxval (inclusive) based on a color_palette representing the range.
"""
max_index = len(color_palette)-1
delta = maxval - minval
if delta == 0:
delta = 1
v = float(val-minval) / delta * max_index
i1, i2 = int(v), min(int(v)+1, max_index)
(r1, g1, b1), (r2, g2, b2) = color_palette[i1], color_palette[i2]
f = v - i1
return int(r1 + f*(r2-r1)), int(g1 + f*(g2-g1)), int(b1 + f*(b2-b1))
def degrees_gradient(im, rect, color_func, color_palette, degrees):
minval, maxval = 1, len(color_palette)
delta = maxval - minval
min_d, max_d = rect.min_max_rot_x(degrees)
range_d = max_d - min_d
for x in range(rect.min.x, rect.max.x + 1):
for y in range(rect.min.y, rect.max.y+1):
p = Point(x, y)
f = (p.rot_x(degrees) - min_d) / range_d
val = minval + f * delta
color = color_func(minval, maxval, val, color_palette)
im.putpixel((x, y), color)
def gradient_image(color_palette, degrees):
region = Rect(0, 0, 600, 400)
width, height = region.max.x+1, region.max.y+1
image = Image.new("RGB", (width, height), WHITE)
degrees_gradient(image, region, gradient_color, color_palette, -degrees)
return image
This flexibility comes at the cost of having to set colors pixel by pixel instead of using lines.