This is what I have. I need to print the surface area
def compute_surface_area_cylindar(radius, height):
surface_area = 2 * math.pi * r * h + 2 * math.pi * math.pow(r, 2)
return surface_area
radius = input("Radius of circle:")
radius = int(radius)
r = radius
height = input("Height of the cylinder:")
height = int(height)
h = height
Here's how you would do it:
import math # You forgot this
def compute_surface_area_cylindar(radius, height):
surface_area = 2 * math.pi * r * h + 2 * math.pi * math.pow(r, 2)
return surface_area
radius = input("Radius of circle:")
radius = int(radius)
r = radius
height = input("Height of the cylinder:")
height = int(height)
h = height
print compute_surface_area_cylindar(radius,height)
The above code will output the surface area of the cylinder based on radius and height, assuming the formula above is correct.
import math
def compute_surface_area_cylindar(radius, height):
surface_area = 2 * math.pi * radius * height + 2 * math.pi * math.pow(radius, 2)
return surface_area
radius = int(input("Radius of circle:"))
#take this out "radius = int(radius)" and you save a line
#take this out an you save a line "r = radius"
height = int(input("Height of the cylinder:"))
# take this out and you save a line "height = int(height) "
#h = height
print(compute_surface_area_cylindar(radius,height))
Related
I try smth like this:
def main_rec():
width = random.randint(150, 250)
height = random.randint(150, 250)
angle = rand_angle()
c, s = np.cos(angle), np.sin(angle)
R = np.array(((c, -s), (s, c)))
center = (random.randint(0, 640), random.randint(0, 480))
x1y10 = (center[0] - width / 2, center[1] + height / 2)
x2y20 = (x1y10[0] + width, x1y10[1])
x3y30 = (x2y20[0], x2y20[1] - height)
x4y40 = (x3y30[0] - width, x3y30[1])
x1y1 = (x1y10[0] * R[0][0] + x1y10[1] * R[0][1], x1y10[0] * R[1][0] + x1y10[1] * R[1][1])
x2y2 = (x2y20[0] * R[0][0] + x2y20[1] * R[0][1], x1y10[1] * R[0][1] + x2y20[1] * R[1][1])
x3y3 = (x3y30[0] * R[0][0] + x3y30[1] * R[0][1], x3y30[0] * R[1][0] + x3y30[1] * R[1][1])
x4y4 = (x4y40[0] * R[0][0] + x4y40[1] * R[0][1], x4y40[1] * R[0][1] + x4y40[1] * R[1][1])
points = [x1y1, x2y2, x3y3, x4y4]
return points, angle / 3.14159 * 180
but I don't know how to set a condition for the corners to be right. I try to use rotation matrix. It makes normal rectangles only for angle = 0
using numpy and rotation matrix code would be:
import numpy as np
import matplotlib.pyplot as plt
def create_rect(width,height,center):
x,y = center
w,h = width,height
return np.array([[x-w/2,y-h/2],
[x+w/2,y-h/2],
[x+w/2,y+h/2],
[x-w/2,y+h/2],
[x-w/2,y-h/2]]).T
width = np.random.randint(150,250)
height = np.random.randint(150,250)
center = (np.random.randint(0, 640), np.random.randint(0, 480))
angle = np.random.randint(0,360)/360.0*2*np.pi
rotmat = np.array([[np.cos(angle),-np.sin(angle)],
[np.sin(angle),np.cos(angle)]])
rect = create_rect(width,height,center)
rot_rect = rotmat # rect
plt.imshow(*rot_rect)
Having a dataset of aligned objects, I would like to augment it by applying random rotations with the axis at the center of the object. Below is the rotation representation (left original, right image rotated around the point (xc, yc).
for rotation, I have used the following logic:
import cv2
import random
image_source = cv2.imread('sample.png')
height, width = image_source.shape[:2]
random_angle = random.uniform(90, 90)
yolo_annotation_sample = get_annotation() # this function retrieves yolo annotation
label_id, xc, yc, object_width, object_height = yolo_annotation_sample # e.g. 4, 0.0189, 0.25, 0.0146, 0.00146
center_x = width * xc
center_y = height * yc
left = center_x - (width * object_width) / 2
top = center_y - (height * object_height) / 2
right = left + width * object_width
bottom = top + height * object_height
M = cv2.getRotationMatrix2D((cx, cy), random_angle, 1.0)
image_rotated = cv2.warpAffine(image_source, M, (width, height))
# logic for calculating new point position (doesn't work)
x1_y1 = np.asarray([[left, top]])
x1_y1_new = np.dot(x1_y1, M)
x2_y2 = np.asarray([[right, top]])
x2_y2_new = np.dot(x2_y2, M)
x3_y3 = np.asarray([[right, bottom]])
x3_y3_new = np.dot(x3_y3, M)
x4_y4 = np.asarray([[left, bottom]])
x4_y4_new = np.dot(x4_y4, M)
Does anyone know how to recalculate the point(s) after rotating around the arbitrary point as shown above?
Use cv2.transform(points, M). Points with shape: (4, 1, 2). Full code:
import cv2
import random
import numpy as np
image_source = cv2.imread('sample.png')
height, width = image_source.shape[:2]
random_angle = 40 #random.uniform(90, 90)
yolo_annotation_sample = (4, 0.6189, 0.25, 0.246, 0.0846) # this function retrieves yolo annotation
label_id, xc, yc, object_width, object_height = yolo_annotation_sample
center_x = width * xc
center_y = height * yc
left = center_x - (width * object_width) / 2
top = center_y - (height * object_height) / 2
right = left + width * object_width
bottom = top + height * object_height
cx, cy = width / 2, height / 2
M = cv2.getRotationMatrix2D((cx, cy), random_angle, 1.0)
image_rotated = cv2.warpAffine(image_source, M, (width, height))
# logic for calculating new point position (doesn't work)
bbox_points = [[left, top], [right, top], [right, bottom], [left, bottom]]
bbox_points = np.array(bbox_points).reshape((-1,1,2))
rotated_points = cv2.transform(bbox_points, M) # what you need
cv2.polylines(image_source,[bbox_points.astype(int)],True,(255,100,0), 10)
cv2.polylines(image_rotated,[rotated_points.astype(int)],True,(255,100,0), 10)
cv2.imshow("orig", image_source)
cv2.imshow("rotated", image_rotated)
cv2.waitKey()
Look at [https://en.wikipedia.org/wiki/Transformation_matrix][1]
Once I tried to calculate it myself:
class rotm :
'''set up rotation matrix'''
def __init__(self,axis,angle,unit="radians") :
self.m = scipy.zeros((4,4),scipy.float128)
if unit=="radians" :
angler = angle
else :
angler = math.radians(angle)
pass
if axis=='x' :
self.m[0][0]=1.0
self.m[1][1]=math.cos(angler)
self.m[2][2]=self.m[1][1]
self.m[3][3]=1.0
self.m[1][2]=-math.sin(angler)
self.m[2][1]=-self.m[1][2]
elif axis=='y' :
self.m[0][0]=math.cos(angler)
self.m[1][1]=1.0
self.m[2][2]=self.m[0][0]
self.m[3][3]=1.0
self.m[0][2]=math.sin(angler)
self.m[2][0]=-self.m[0][2]
elif axis=='z' :
self.m[0][0]=math.cos(angler)
self.m[1][1]=self.m[0][0]
self.m[2][2]=1.0
self.m[3][3]=1.0
self.m[0][1]=-math.sin(angler)
self.m[1][0]=-self.m[0][1]
pass
pass
def fPrint(self) :
'''auxiliary function: print transformation matrix '''
print(self.m)
pass
pass #end of rotm class
I want a commet in pygame to shoot across the screen. Here is my commet class
class Commet:
def __init__(self):
self.x = -10
self.y = 10
self.radius = 20
self.commet = pygame.image.load(r"C:\Users\me\OneDrive\Documents\A level python codes\final game\commet.png")
self.commet = pygame.transform.scale(self.commet, (self.radius, self.radius))
self.drop = 0.0000009
self.speed = 2
self.pos = 0
self.commets = []
Then i added 20 commets to the self.commets list.
def tail(self, n): # n is a variable used to denote the length of the self.commets
for i in range(n):
if len(self.commets) <= n - 1:
self.commets.append(Commet())
I am having two problems. The first problem being moving the commet. To move it i did this
def move_tail(self):
for c in self.commets:
c.x += self.speed
for i in range(len(self.commets) - 1):
self.commets[i].y += ((self.commets[i + 1].x) ** 2) * self.drop
For x- coordinate i just added 2 to its value every frame. However, for the yvalue of the commet, i want it to produce a tail-like following effect. I tried assigning the y value of the commet to the square of x value of the commet in the index position one above the commet we are referring to in the list self.commets.I expected the commets to follow each other along a general x = y **2 quadradic curve. They do follow the curve but all at the same rate(i expected them to follow at different rate because all the commets have different x values), which dosent give me the tail-like effect. How would i be able to produce this tail-like effect?
The second part of my question is that i want the commets following the first one get smaller and smaller. I tried decreasing the radius value, which is used to scale the image i imported. The code looks like this
# Decrease radius
for i in range(n):
self.commets[i].radius = i + 1
When i print out the values of radius of the commets on the console, they range from 1 to 20, as i expect them to, but the size of the image that appears on the screen is the same for all the commets in the list.The following code is how i blit the commet
for i in range(n):
self.commets[i].pos = i * 10 # This line maintains a certain x- distance between commets
for c in self.tails:
D.blit(c.commet, (c.x - c.pos, c.y))
if self.pos >= n:
self.pos = n
Given you want your comet to fly from left to right on a FullHD screen.
The comet shall start at the left side at a y coordinate of 900, then reach its highest point at x=1400 and y = 100 and then fall to 600 at the right side of the screen.
A parabola is generally y = ax²+bx+c.
To be independent of the screen resolution, you would of course calculate those values from some percentage, say 900 ~ screen height * 83%, 600 ~ screen height * 55%, 1400 ~ screen width * 73%, 100 ~ screen height * 9%
With three points given, you can calculate a parabola:
class ParabolaFrom3Points:
def __init__(self, points: list):
self.a = (points[0][0] * (points[1][1] - points[2][1]) + points[1][0] * (
points[2][1] - points[0][1]) + points[2][0] * (points[0][1] - points[1][1])) / (
(points[0][0] - points[1][0]) * (points[0][0] - points[2][0]) * (
points[2][0] - points[1][0]))
self.b = (points[0][0] ** 2 * (points[1][1] - points[2][1]) + points[1][0] ** 2 * (
points[2][1] - points[0][1]) + points[2][0] ** 2 * (points[0][1] - points[1][1])) / (
(points[0][0] - points[1][0]) * (points[0][0] - points[2][0]) * (
points[1][0] - points[2][0]))
self.c = (points[0][0] ** 2 * (points[1][0] * points[2][1] - points[2][0] * points[1][1]) +
points[0][0] * (points[2][0] ** 2 * points[1][1] - points[1][0] ** 2 * points[2][1]) +
points[1][0] * points[2][0] * points[0][1] * (points[1][0] - points[2][0])) / (
(points[0][0] - points[1][0]) * (points[0][0] - points[2][0]) * (
points[1][0] - points[2][0]))
def y(self, x: int) -> int:
return int(self.a * x ** 2 + self.b * x + self.c)
The Comet is quite simple then. It just needs to know its parabola function and can then calculate the y from the x.
class Comet:
def __init__(self, radius: int, para: ParabolaFrom3Points):
self.x = -radius # Be invisible at the beginning
self.radius = radius
self.para = para
def move(self, x):
self.x = x
def paint(self, screen):
x = self.x
radius = self.radius
for tail in range(20):
pygame.draw.circle(screen, [255, 255, 255], (int(x), self.para.y(x)), radius)
x = x - radius / 2
radius -= 1
Test code:
import pygame
pygame.init()
pygame.fastevent.init()
clock = pygame.time.Clock()
window = pygame.display.set_mode((1920, 1080))
pygame.display.set_caption('Comet example')
comet = Comet(20, ParabolaFrom3Points([(0, 1080 * 0.83), (1920 * 0.73, 1080 * 0.12), (1920, 1080 * 0.55)]))
for x in range(-20, 1920 + 200, 3):
comet.move(x)
comet.paint(window)
clock.tick(90)
pygame.display.flip()
window.fill([0, 0, 0])
pygame.quit()
I am attempting to draw a speedometer using a Tkinter Canvas in Python and am having a few problems with my code that I can't seem to figure out. First off, here is what I have written:
import tkinter as tk
from tkinter import ttk
import math
class DrawMeter(tk.Canvas):
def __init__(self, parent, *args, **kwargs):
tk.Canvas.__init__(self, parent, *args, **kwargs)
self.config(bg = "grey")
if (int(self['height']) * 2 > int(self['width'])):
boxSide = int(self['width'])
else:
boxSide = int(self['height']) * 2
self.boxX = boxSide / 2
self.boxY = boxSide / 2
self.boxRadius = int(0.40 * float(boxSide))
self.start = 0
self.end = 1
self.drawBackground()
self.drawTicks()
self.drawNeedle()
def drawBackground(self):
bgColour = "black"
self.create_arc((self.boxX - self.boxRadius,
self.boxY - self.boxRadius,
self.boxX * 4,
self.boxY * 4),
fill = bgColour, start = 90)
def drawTicks(self):
length = self.boxRadius / 8
for deg in range(5, 85, 6):
rad = math.radians(deg)
self.Tick(rad, length)
for deg in range(5, 91, 18):
rad = math.radians(deg)
self.Tick(rad, length * 2)
def Tick(self, angle, length):
cos = math.cos(angle)
sin = math.sin(angle)
radius = self.boxRadius * 2
X = self.boxX * 2
Y = self.boxY * 2
self.create_line((X - radius * cos,
Y - radius * sin,
X - (radius - length) * cos,
Y - (radius - length) * sin),
fill = "white", width = 2)
def drawText(self, start = 0, end = 100):
interval = end / 5
value = start
length = self.boxRadius / 2
for deg in range(5, 91, 18):
rad = math.radians(deg)
cos = math.cos(rad)
sin = math.sin(rad)
radius = self.boxRadius * 2
self.create_text(self.boxX * 2 - (radius - length - 1) * cos,
self.boxY * 2 - (radius - length - 1) * sin,
text = str("{0:.1f}".format(value)),
fill = "white",
font = ("Arial", 12, "bold"))
value = value + interval
def setRange(self, start, end):
self.start = start
self.end = end
self.drawText(start, end)
def drawNeedle(self):
X = self.boxX * 2
Y = self.boxY * 2
length = self.boxRadius - (self.boxRadius / 4)
self.meterHand = self.create_line(X / 2, Y / 2, X + length, Y + length,
fill = "red", width = 4)
self.create_arc(X - 30, Y - 30, X + 30, Y + 30,
fill = "#c0c0c0", outline = "#c0c0c0", start = 90)
def updateNeedle(self, value):
length = self.boxRadius - (self.boxRadius / 4)
deg = 80 * (value - self.start) / self.end - 180
rad = math.radians(deg)
self.coords(self.meterHand, self.boxX * 2, self.boxY * 2,
self.boxX + length * math.cos(rad),
self.boxY + length * math.sin(rad))
value = 0
def update_frame():
global value
if value < 1:
value = value + 0.01
print(value)
meter.updateNeedle(value)
container.after(200, update_frame)
root = tk.Tk()
container = tk.Frame(root)
container.pack()
meter = DrawMeter(container, height = 200, width = 200, bg = "red")
meter.setRange(0, 1)
meter.pack()
update_frame()
root.mainloop()
So the problem is I am having is that my needle is drawing and updating properly on the screen. When I start the program, the needle starts at around 0.2ish, and goes until about 0.6 and then stop. I feel like my formula for calculating the needle's position is wrong, but I am not sure what about it is wrong.
The way I have it set up, is it takes the the percentage of the total the value is (value = self.start) / self.end) and multiplies it by 80 degrees (because my speedometer starts at the 5 degree marks and ends at 85) and them subtracts 180 so that the number makes the number go clockwise, not counter clockwise.
My placement of the canvas objects could also be off. My attempt was to set up a Speedometer that is a quarter circle at the bottom of the Canvas. However when you use the Canvas create_arc function, it draws the bottom right corner of your arc, in the center of the bounding box, meaning you make it the bottom right corner, I need to make by bounding box double the width and height of the canvas. I'm thinking maybe that threw me off a bit as well.
My problem was that I needed to create an offset value and add it to all four points in the Canvas.coords call.
From given image I want to bring flat surface to 180 degree i.e at the bottom. Following code i have tried..
def get_line(img):
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray, 50, 150, apertureSize=3)
lines = cv2.HoughLines(edges, 1, np.pi / 180, 50)
for rho, theta in lines[0]:
a = np.cos(theta)
b = np.sin(theta)
x0 = a * rho
y0 = b * rho
x1 = int(x0 + 1000 * (-b))
y1 = int(y0 + 1000 * (a))
x2 = int(x0 - 1000 * (-b))
y2 = int(y0 - 1000 * (a))
# cv2.line(img,(x1,y1),(x2,y2),(0,0,255),2)
# print(x1, x2, y1, y2)
cx = int((x1 + x2) / 2)
cy = int((y1 + y2) / 2)
# print("abc",cx, cy)
deg = math.degrees(math.atan2(cx, cy))
print(deg)
# cv2.circle(img,(cx,cy),5,(0,255,0),-1)
cv2.imshow('frame', img)
cv2.waitKey(0)
return cx, cy
def rotation():
img=cv2.imread("pr43.jpg")
cx,cy=get_line(img)
height, width, _ = img.shape
# print(width, height)
xpercent = int(abs((cx / width) * 100))
ypercent = int(abs((cy / height) * 100))
# print ("XPercent",xpercent)
# print("YPercent",ypercent)
# print("xpercent, ypercent", xpercent, ypercent)
if xpercent > 50:
print("point in right palne and vertical")
# Todo: rotate clock by 90*
r = imutils.rotate_bound(img, 90)
cv2.imshow("roatated", r)
cv2.waitKey(0)
elif xpercent > 0 and 0 < ypercent < 50:
print("point in upper left plane and vertical")
# Todo: rotate anti-clock by 90*
r = imutils.rotate_bound(img, -90)
cv2.imshow("roatated", r)
cv2.waitKey(0)
elif xpercent <= 0:
print("point in upper left plane and Horizontal")
# Todo: rotate clock by 180*
r = imutils.rotate_bound(img, 180)
cv2.imshow("roatated", r)
elif xpercent < 50 and ypercent > 50:
print("No rotation needed")
r = img
cv2.imwrite("Output_Image.jpg", r)
Below is my output of the code
From this code I'am getting 50% correct output but the surface is not coming at 180 degree. As i cant keep the image angle static because image angle will vary but i have to bring flat surface to Bottom.