I have made this algorithm myself based on how to rotate an image.
import cv2
import math
import numpy as np
class rotation:
angle = 60.0
x = 100
y = 100
img = cv2.imread('FNAF.png',0)
width,height = img.shape
def showImage(name, self):
cv2.imshow(name, self.img)
def printWidthHeight(self):
print(self.width)
print(self.height)
def rotateImage(self):
ForwardMap = np.zeros((self.width,self.height),dtype="uint8")
BackwardMap = np.zeros((self.width,self.height),dtype="uint8")
for i in range(self.width):
for j in range(self.height):
# forward mapping
for_x = (i - self.x) * math.cos(self.angle*(math.pi/180)) - (j - self.y) * math.sin(self.angle*(math.pi/180)) + self.x
for_y = (i - self.x) * math.sin(self.angle*(math.pi/180)) + (j - self.y) * math.cos(self.angle*(math.pi/180)) + self.x
for_x = int(for_x)
for_y = int(for_y)
# backward mapping should change the forward mapping to the original image
back_x = (i - self.x) * math.cos(self.angle*(math.pi/180)) + (j - self.y) * math.sin(self.angle*(math.pi/180)) + self.x
back_y = -(i - self.x) * math.sin(self.angle*(math.pi/180)) + (j - self.y) * math.cos(self.angle*(math.pi/180)) + self.x
back_x = int(back_x)
back_y = int(back_y)
if for_x in range(self.width) and for_y in range(self.height):
ForwardMap[i, j] = self.img[for_x, for_y]
else:
pass
if back_x in range(self.width) and back_y in range(self.height):
BackwardMap[i, j] = self.img[back_x, back_y]
else:
pass
cv2.imshow('Forward Mapping', ForwardMap)
cv2.imshow('Backward Mapping', BackwardMap)
def demo():
rotation.showImage('normal', rotation)
rotation.printWidthHeight(rotation)
rotation.rotateImage(rotation)
cv2.waitKey(0)
cv2.destroyAllWindows
if __name__ == '__main__':
demo()
My problem is now that I want to make the rotated pictures (both for forward and backwards mapping) fit JUST right so there is no unnecessary use of space. Can anybody help me with this? Much appreciated.
If you have any suggestions to optimize my code, feel free to comment on that as well.
Your original image has 4 corners, coordinates: (0,0), (w-1, 0), (0,h-1) and (w-1, h-1). Since your transformation is affine, why not transform these coordinates into destination coordinates?
(0,0) → (x1, y1)
(w-1, 0) → (x2, y2)
(0, h-1) → (x3, y3)
(w-1, h-1) → (x4, y4)
Your destination image size is then:
width = max(x1, x2, x3, x4) - min(x1, x2, x3, x4)
height = max(y1, y2, y3, y4) - min(y1, y2, y3, y4)
Related
I managed to find in someone who made a class for rounded buttons in tkinter that works great. However the issue I have is there is always a white border.
I've tried reading through all of the code and changing all of the colour values but to no avail.
Here is an excerpt of the code working, I've tried to format it as nicely as I could:
from tkinter import Tk, Canvas
class RoundedButton(Canvas):
def __init__(self, master=None, text: str = "", radius=25, btnforeground="#007CEE", btnbackground="#ffffff",
clicked=None, font=("Righteous", 25), *args, **kwargs):
super(RoundedButton, self).__init__(master, *args, **kwargs)
self.config(bg=self.master["bg"])
self.btnbackground = btnbackground
self.btnforeground = btnforeground
self.clicked = clicked
self.radius = radius
self.rect = self.round_rectangle(0, 0, 0, 0, tags="button", radius=radius, fill=btnbackground)
self.text = self.create_text(0, 0, text=text, tags="button", fill=btnforeground, font=font,
justify="center")
self.tag_bind("button", "<ButtonPress>", self.border)
self.tag_bind("button", "<ButtonRelease>", self.border)
self.bind("<Configure>", self.resize)
text_rect = self.bbox(self.text)
if int(self["width"]) < text_rect[2] - text_rect[0]:
self["width"] = (text_rect[2] - text_rect[0]) + 10
if int(self["height"]) < text_rect[3] - text_rect[1]:
self["height"] = (text_rect[3] - text_rect[1]) + 10
def round_rectangle(self, x1, y1, x2, y2, radius=25, update=False,
**kwargs): # if update is False a new rounded rectangle's id will be returned else updates existing rounded rect.
# source: https://stackoverflow.com/a/44100075/15993687
points = [x1 + radius, y1,
x1 + radius, y1,
x2 - radius, y1,
x2 - radius, y1,
x2, y1,
x2, y1 + radius,
x2, y1 + radius,
x2, y2 - radius,
x2, y2 - radius,
x2, y2,
x2 - radius, y2,
x2 - radius, y2,
x1 + radius, y2,
x1 + radius, y2,
x1, y2,
x1, y2 - radius,
x1, y2 - radius,
x1, y1 + radius,
x1, y1 + radius,
x1, y1]
if not update:
return self.create_polygon(points, **kwargs, smooth=True)
else:
self.coords(self.rect, points)
def resize(self, event):
text_bbox = self.bbox(self.text)
if self.radius > event.width or self.radius > event.height:
radius = min((event.width, event.height))
else:
radius = self.radius
width, height = event.width, event.height
if event.width < text_bbox[2] - text_bbox[0]:
width = text_bbox[2] - text_bbox[0] + 30
if event.height < text_bbox[3] - text_bbox[1]:
height = text_bbox[3] - text_bbox[1] + 30
self.round_rectangle(5, 5, width - 5, height - 5, radius, update=True)
bbox = self.bbox(self.rect)
x = ((bbox[2] - bbox[0]) / 2) - ((text_bbox[2] - text_bbox[0]) / 2)
y = ((bbox[3] - bbox[1]) / 2) - ((text_bbox[3] - text_bbox[1]) / 2)
self.moveto(self.text, x, y)
def border(self, event):
if event.type == "4":
self.itemconfig(self.rect, fill="#DE8500")
self.itemconfig(self.text, fill='#ffffff')
if self.clicked is not None:
self.clicked()
else:
self.itemconfig(self.rect, fill=self.btnbackground)
self.itemconfig(self.text, fill=self.btnforeground)
window = Tk()
window.geometry("1440x872")
window.configure(bg="#007CEE")
download_button_1 = RoundedButton(
text="Download",
font=("Righteous", 30),
borderwidth=0)
download_button_1.place(
x=409,
y=383,
width=621.0,
height=105.0
)
window.mainloop()
EDIT: Furas' answer works perfect, for anyone interested in using this rounded button class I would reccommend changing the splinesteps to a higher value at self.create_polygon to help with smoothing
return self.create_polygon(points, **kwargs, smooth=True, splinesteps=10000)
On Linux works for me
highlightthickness=0
or set color of background
highlightbackground="#007CEE"
eventually
borderwidth=-1
Doc for Canvas (page effbot.org on archive.org) shows all config options.
Before:
After:
2023.01.28:
Using: Pop!_OS 22.04 LTS //Python 3.10.6// Tcl/Tk V.8.6
"borderwidth=-1" did not seem to work, but "highlightthickness=0" appeared to do exactly what I expected.
Resulting button with rounded corners
And I used an exact copy of the code posted in the original question (by: Cai Allin,Mar 10, 2022 at 21:21)
My only changes were in the block for the "Rounded button".
First I tested to change the "borderwidth"
download_button_1 = RoundedButton(
text="Download",
font=("Righteous", 30),
borderwidth=-1,
)
But this did not result in any visible change.
I then tested to just below the "borderwidth" add:
highlightthickness=0
And this change succeeded in removing the "white border", and it worked regardless whether the settings for the "borderwidth" was "-1" or "0"
I managed to find in someone who made a class for rounded buttons in tkinter that works great. However the issue I have is there is always a white border.
I've tried reading through all of the code and changing all of the colour values but to no avail.
Here is an excerpt of the code working, I've tried to format it as nicely as I could:
from tkinter import Tk, Canvas
class RoundedButton(Canvas):
def __init__(self, master=None, text: str = "", radius=25, btnforeground="#007CEE", btnbackground="#ffffff",
clicked=None, font=("Righteous", 25), *args, **kwargs):
super(RoundedButton, self).__init__(master, *args, **kwargs)
self.config(bg=self.master["bg"])
self.btnbackground = btnbackground
self.btnforeground = btnforeground
self.clicked = clicked
self.radius = radius
self.rect = self.round_rectangle(0, 0, 0, 0, tags="button", radius=radius, fill=btnbackground)
self.text = self.create_text(0, 0, text=text, tags="button", fill=btnforeground, font=font,
justify="center")
self.tag_bind("button", "<ButtonPress>", self.border)
self.tag_bind("button", "<ButtonRelease>", self.border)
self.bind("<Configure>", self.resize)
text_rect = self.bbox(self.text)
if int(self["width"]) < text_rect[2] - text_rect[0]:
self["width"] = (text_rect[2] - text_rect[0]) + 10
if int(self["height"]) < text_rect[3] - text_rect[1]:
self["height"] = (text_rect[3] - text_rect[1]) + 10
def round_rectangle(self, x1, y1, x2, y2, radius=25, update=False,
**kwargs): # if update is False a new rounded rectangle's id will be returned else updates existing rounded rect.
# source: https://stackoverflow.com/a/44100075/15993687
points = [x1 + radius, y1,
x1 + radius, y1,
x2 - radius, y1,
x2 - radius, y1,
x2, y1,
x2, y1 + radius,
x2, y1 + radius,
x2, y2 - radius,
x2, y2 - radius,
x2, y2,
x2 - radius, y2,
x2 - radius, y2,
x1 + radius, y2,
x1 + radius, y2,
x1, y2,
x1, y2 - radius,
x1, y2 - radius,
x1, y1 + radius,
x1, y1 + radius,
x1, y1]
if not update:
return self.create_polygon(points, **kwargs, smooth=True)
else:
self.coords(self.rect, points)
def resize(self, event):
text_bbox = self.bbox(self.text)
if self.radius > event.width or self.radius > event.height:
radius = min((event.width, event.height))
else:
radius = self.radius
width, height = event.width, event.height
if event.width < text_bbox[2] - text_bbox[0]:
width = text_bbox[2] - text_bbox[0] + 30
if event.height < text_bbox[3] - text_bbox[1]:
height = text_bbox[3] - text_bbox[1] + 30
self.round_rectangle(5, 5, width - 5, height - 5, radius, update=True)
bbox = self.bbox(self.rect)
x = ((bbox[2] - bbox[0]) / 2) - ((text_bbox[2] - text_bbox[0]) / 2)
y = ((bbox[3] - bbox[1]) / 2) - ((text_bbox[3] - text_bbox[1]) / 2)
self.moveto(self.text, x, y)
def border(self, event):
if event.type == "4":
self.itemconfig(self.rect, fill="#DE8500")
self.itemconfig(self.text, fill='#ffffff')
if self.clicked is not None:
self.clicked()
else:
self.itemconfig(self.rect, fill=self.btnbackground)
self.itemconfig(self.text, fill=self.btnforeground)
window = Tk()
window.geometry("1440x872")
window.configure(bg="#007CEE")
download_button_1 = RoundedButton(
text="Download",
font=("Righteous", 30),
borderwidth=0)
download_button_1.place(
x=409,
y=383,
width=621.0,
height=105.0
)
window.mainloop()
EDIT: Furas' answer works perfect, for anyone interested in using this rounded button class I would reccommend changing the splinesteps to a higher value at self.create_polygon to help with smoothing
return self.create_polygon(points, **kwargs, smooth=True, splinesteps=10000)
On Linux works for me
highlightthickness=0
or set color of background
highlightbackground="#007CEE"
eventually
borderwidth=-1
Doc for Canvas (page effbot.org on archive.org) shows all config options.
Before:
After:
2023.01.28:
Using: Pop!_OS 22.04 LTS //Python 3.10.6// Tcl/Tk V.8.6
"borderwidth=-1" did not seem to work, but "highlightthickness=0" appeared to do exactly what I expected.
Resulting button with rounded corners
And I used an exact copy of the code posted in the original question (by: Cai Allin,Mar 10, 2022 at 21:21)
My only changes were in the block for the "Rounded button".
First I tested to change the "borderwidth"
download_button_1 = RoundedButton(
text="Download",
font=("Righteous", 30),
borderwidth=-1,
)
But this did not result in any visible change.
I then tested to just below the "borderwidth" add:
highlightthickness=0
And this change succeeded in removing the "white border", and it worked regardless whether the settings for the "borderwidth" was "-1" or "0"
I have a script that creates Circle GraphicsObjects and applies newton's laws to them (gravitational pull), and moves each shape by its respective x,y velocity at each time step.
My goal is to draw a line between each of these circles and to move each line along with each circle every time step.
Circle.move(dx, dy) takes two inputs, but the same method for a line should have 4 inputs for each of the end points of the line. This method does not exist as far as I can tell.
The code in my project may be hard to digest so I added a sample of something similar. I would expect the code below to move the line like the hands of a clock (i.e., one point stays in the center, and the other end of the line rotates around the center in a circle).
I attempted to create a new version of the Line object and give it the move method, but this doesn't work as expected.
from graphics import *
import math, random, time
width = 500
height = 500
win = GraphWin("Example",width,height)
resolution = 10 # steps/lines per rotation
centerX = width/2
centerY = height/2
radius1 = 300
P1 = Point(centerX,centerY)
class newLine(Line):
def move(self, dx1, dy1, dx2, dy2):
self.p1.x = self.p1.x + dx1
self.p1.y = self.p1.y + dy1
self.p2.x = self.p2.x + dx2
self.p2.y = self.p2.y + dy2
circleX = centerX+radius1*math.cos(2*math.pi*0/resolution)
circleY = centerY+radius1*math.sin(2*math.pi*0/resolution)
P2 = Point(circleX,circleY)
L1 = newLine(P1,P2)
L1.draw(win)
for i in range(resolution):
circleX2 = centerX+radius1*math.cos(2*math.pi*(i+1)/resolution)
circleY2 = centerY+radius1*math.sin(2*math.pi*(i+1)/resolution)
dx = circleX2-circleX
dy = circleY2-circleY
L1.move(0,0,dx,dy)
time.sleep(0.2)
win.getMouse()
win.close()
First idea:
Remove old line using undraw() and next create new Line and draw it.
It can be the only method - because it uses tkinter.Canvas and it can't rotate when it moves.
l1.undraw()
p2 = Point(circle_x, circle_y)
l1 = Line(p1, p2)
l1.draw(win)
Full working code
from graphics import *
import math
import random
import time # PEP8: every module in separated line
# --- constansts --- # PEP8: `UPPER_CASE_NAMES`
WIDTH = 500
HEIGHT = 500
# --- classes --- # PEP8: `CamelCaseNames`
# empty
# --- main ---- # PEP8: `lower_case_names`
# PEP8: space after comma
win = GraphWin("Example", WIDTH, HEIGHT)
resolution = 10 # steps/lines per rotation # PEP8: two spaces before #
center_x = WIDTH/2
center_y = HEIGHT/2
radius = 100
p1 = Point(center_x, center_y)
value = 0 # `2 * math.pi * 0 / resolution` gives `0`
circle_x = center_x + radius * math.cos(value)
circle_y = center_y + radius * math.sin(value)
p2 = Point(circle_x, circle_y)
l1 = Line(p1, p2)
l1.draw(win)
time.sleep(0.1)
for r in range(3): # repeat 3 times
for i in range(1, resolution+1):
value = 2 * math.pi * (i / resolution)
circle_x = center_x + radius * math.cos(value)
circle_y = center_y + radius * math.sin(value)
l1.undraw()
p2 = Point(circle_x, circle_y)
l1 = Line(p1, p2)
l1.draw(win)
time.sleep(0.1)
win.getMouse()
win.close()
PEP 8 -- Style Guide for Python Code
BTW:
You can get full path to source code
import graphics
print( graphics.__file__ )
and you can check how move() works - maybe it use the same method.
EDIT:
Digging in source code I got another idea - use Polygon which has list of points and you can move last point - but it needs to calculate dx, dy - or simpler you can replace last point.
But both methods needs ot use undraw() + draw() to refresh screen.
Teoretically update() should refresh screen but it doesn't do it.
p2 = Point(circle_x, circle_y)
l1 = Polygon(p1, p2)
l1.draw(win)
time.sleep(0.1)
for i in range(1, resolution+1):
value = 2 * math.pi * (i / resolution)
new_circle_x = center_x + radius * math.cos(value)
new_circle_y = center_y + radius * math.sin(value)
dx = new_circle_x - circle_x
dy = new_circle_y - circle_y
l1.points[-1].move(dx, dy)
circle_x = new_circle_x
circle_y = new_circle_y
# ---
# force to redraw it
l1.undraw()
l1.draw(win)
#update() # doesn't redraw it
time.sleep(0.1)
or
p2 = Point(circle_x, circle_y)
l1 = Polygon(p1, p2)
l1.draw(win)
time.sleep(0.1)
for i in range(1, resolution+1):
value = 2 * math.pi * (i / resolution)
circle_x = center_x + radius * math.cos(value)
circle_y = center_y + radius * math.sin(value)
p2 = Point(circle_x, circle_y)
l1.points[-1] = p2
# ---
# force to redraw it
l1.undraw()
l1.draw(win)
#update() # doesn't redraw it
time.sleep(0.1)
EDIT:
After digging in source code I created
class NewLine(Line):
def move(self, dx1, dy1, dx2, dy2):
self.p1.x += dx1
self.p1.y += dy1
self.p2.x += dx2
self.p2.y += dy2
canvas = self.canvas
self.undraw()
self.draw(canvas)
or
class NewLine(Line):
def move(self, dx1, dy1, dx2, dy2):
self.p1.x += dx1
self.p1.y += dy1
self.p2.x += dx2
self.p2.y += dy2
self.canvas.coords(self.id, self.p1.x, self.p1.y, self.p2.x, self.p2.y)
self.canvas.update()
#update() # it needs `from graphics import *`
In similar way it can move end point.
class NewLine(Line):
def _change(self):
#canvas = self.canvas
#self.undraw()
#self.draw(canvas)
# OR
self.canvas.coords(self.id, self.p1.x, self.p1.y, self.p2.x, self.p2.y)
self.canvas.update()
#update() # it needs `from graphics import *`
def moveP2ToXY(self, x, y):
self.p2.x = x
self.p2.y = y
self._change()
def moveP2ToPoint(self, point):
self.p2.x = point.x
self.p2.y = point.y
self._change()
def move(self, dx1, dy1, dx2, dy2):
self.p1.x += dx1
self.p1.y += dy1
self.p2.x += dx2
self.p2.y += dy2
self._change()
def moveTo(self, x1, y1, x2, y2):
self.p1.x = x1
self.p1.y = y1
self.p2.x = x2
self.p2.y = y2
self._change()
I am trying to build a subclass that inherited from turtle.Turtle class and want to create a function to automatically draw the polygon. But I find the initial line always tilts a bit.
I don't know where's the problem.
Here's the code:
import turtle
class Polygon(turtle.Turtle):
def __init__(self, point_list):
self.point_list = point_list
def add_point(self, point):
self.point_list.append(point)
return self.point_list
def over_write_points(self, new_points):
self.point_list = new_points
return self.point_list
def perimeter(self):
length_peri = 0
for i in range(len(self.point_list)):
point1 = self.point_list[i-1]
point2 = self.point_list[i]
x1, y1 = point1
x2, y2 = point2
length = ((x1 - x2)**2 + (y1 - y2)**2)*0.5
length_peri += length
return length_peri
def area(self):
area = 0
for i in range(len(self.point_list)):
point1 = self.point_list[i-1]
point2 = self.point_list[i]
x1, y1 = point1
x2, y2 = point2
trapezoid = ((x2 - x1) * (y1 + y2)) / 2
area = area + trapezoid
area = abs(area)
return area
def bound_points(self):
unzip_list = list(zip(*self.point_list))
x_list = unzip_list[0]
y_list = unzip_list[1]
bound1 = max(x_list), min(y_list)
bound2 = max(x_list), max(y_list)
bound3 = min(x_list), max(y_list)
bound4 = min(x_list), min(y_list)
bound_points = [bound1, bound2, bound3, bound4]
return bound_points
def move_poly(self, dx, dy):
new_point_list = []
for i in self.point_list:
x = i[0] + dx
y = i[1] + dy
new_point = (x, y)
new_point_list.append(new_point)
self.point_list = new_point_list
return self.point_list
def draw_poly(self, lineColour="green", fillColour="yellow"):
start = self.point_list[-1]
turtle.pencolor(lineColour)
turtle.fillcolor(fillColour)
turtle.penup()
turtle.pendown()
turtle.begin_fill()
x, y = start
for point in self.point_list: # go through a list of points
dx, dy = point
turtle.goto(x + dx, y + dy)
turtle.end_fill()
turtle.penup()
turtle.mainloop()
return f'The polygon is finished'
test_polygon = Polygon([(50,0), (50,50), (0,50)])
print(test_polygon.add_point((0, 0)))
print(test_polygon.over_write_points([(100,0), (100,100), (0,100), (0,0)]))
print(test_polygon.perimeter())
print(test_polygon.area())
print(test_polygon.bound_points())
print(test_polygon.move_poly(-10,-10))
print(test_polygon.draw_poly())
You've several problems in your code. First, as #martineau notes (+1), you start drawing from the turtle's home position rather than the first position in your list. (And you need to close the polygon by returning back to that first position.)
The math in your perimeter() function seems wrong:
length = ((x1 - x2)**2 + (y1 - y2)**2)*0.5
That should probably be **0.5 to calculate the square root, not half. You forgot to call super() in your __init__ function.
Also, your draw_poly() is calling functions in module turtle instead of invoking methods on self. This is why I do import Screen, Turtle instead of import turtle, just to avoid this error.
Below is a rework of your code with the above and other fixes:
from turtle import Turtle
class Polygon(Turtle):
def __init__(self, point_list):
super().__init__()
self.point_list = point_list
def add_point(self, point):
self.point_list.append(point)
return self.point_list
def over_write_points(self, new_points):
self.point_list[:] = new_points # reload existing list
return self.point_list
def perimeter(self):
length_peri = 0
for i in range(len(self.point_list)):
point1 = self.point_list[i - 1]
point2 = self.point_list[i]
x1, y1 = point1
x2, y2 = point2
length = ((x1 - x2)**2 + (y1 - y2)**2)**0.5
length_peri += length
return length_peri
def area(self):
area = 0
for i in range(len(self.point_list)):
point1 = self.point_list[i - 1]
point2 = self.point_list[i]
x1, y1 = point1
x2, y2 = point2
trapezoid = ((x2 - x1) * (y1 + y2)) / 2
area += trapezoid
return abs(area)
def bound_points(self):
unzip_list = list(zip(*self.point_list))
x_list = unzip_list[0]
y_list = unzip_list[1]
bound1 = max(x_list), min(y_list)
bound2 = max(x_list), max(y_list)
bound3 = min(x_list), max(y_list)
bound4 = min(x_list), min(y_list)
return [bound1, bound2, bound3, bound4]
def move_poly(self, dx, dy):
new_point_list = []
for x, y in self.point_list:
new_point = (x + dx, y + dy)
new_point_list.append(new_point)
return self.over_write_points(new_point_list)
def draw_poly(self, lineColour='green', fillColour='yellow'):
self.pencolor(lineColour)
self.fillcolor(fillColour)
start, *remaining_points = self.point_list
self.penup()
self.goto(start)
self.pendown()
self.begin_fill()
for point in remaining_points: # go through a list of points
self.goto(point)
self.goto(start)
self.end_fill()
self.penup()
return 'The polygon is finished'
if __name__ == '__main__':
from turtle import Screen
screen = Screen()
test_polygon = Polygon([(50, 0), (50, 50), (0, 50)])
print(test_polygon.add_point((0, 0)))
print(test_polygon.over_write_points([(100, 0), (100, 100), (0, 100), (0, 0)]))
print(test_polygon.perimeter(), "pixels")
print(test_polygon.area(), "pixels squared")
print(test_polygon.bound_points())
print(test_polygon.move_poly(-10, -10))
print(test_polygon.draw_poly())
screen.exitonclick()
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.