[Python] 纯文本查看 复制代码
import random
import tkinter
import os
import math
from PIL import Image, ImageTk, ImageDraw
from tkinter import messagebox
def crop_circle(image):
global center_x, center_y
"""
从图片上截下一个小滑块,
并同时保存小滑块与扣掉小滑块的图片
"""
# 定义裁剪区域(圆形)
center_x = 600 # x圆心的坐标点
center_y = 150 # y圆心的坐标点
radius = 50 # 圆半径大小
x1 = center_x - radius
x2 = center_x + radius
y1 = center_y - radius
y2 = center_y + radius
# 创建一个透明图像作为遮罩
mask = Image.new("L", image.size, 0)
draw = ImageDraw.Draw(mask)
draw.ellipse((x1, y1, x2, y2), fill=255)
# 将遮罩应用于裁剪操作
cropped_small_image = image.copy()
cropped_small_image.putalpha(mask)
cropped_small_image = cropped_small_image.crop((x1, y1, x2, y2))
# 创建一个遮罩的反向版本
inverted_mask = Image.eval(mask, lambda px: 255 - px)
# 从大图中去除圆形区域
cropped_big_image = image.copy()
cropped_big_image.putalpha(inverted_mask)
# 保存裁剪后的小图
cropped_small_image.convert("RGBA").save(small_image_path, format="PNG")
# 保存裁剪后的大图
cropped_big_image.convert("RGBA").save(big_image_path, format="PNG")
# 关闭图像
image.close()
cropped_small_image.close()
cropped_big_image.close()
def on_click(event):
global angle
x1, y1 = center_x-50, center_y-50
x2, y2 = event.x, event.y
dx = x2 - x1
dy = y2 - y1
# 计算鼠标移动点与x基准线的角度,若以Y为基准角度将dy与dx参数互换math.atan2(dx, dy),计算出来的是弧度
# 再用degrees将弧度转为角度
angle1 = math.degrees(math.atan2(dy, dx))
angle = int((angle1 + 360) % 360) # 将角度值限制在0至359度之间
rotated_image = small_img.rotate(angle, center=(small_img.width // 2, small_img.height // 2))
rotated_image_tk = ImageTk.PhotoImage(rotated_image)
canvas.itemconfig(image_item, image=rotated_image_tk)
canvas.image = rotated_image_tk # 更新图像引用
def func(event):
"""
鼠标松开触发事件,
鼠标松开检查图片角度是否是0度
左右各允许3度的误差
"""
if angle <= 3 or angle >= 357:
messagebox.showinfo("信息", "操作成功!")
else:
messagebox.showerror("错误", f"不是这个位置\n")
def update_coordinates(event):
x = event.x
y = event.y
label.config(text=f"X 坐标:{x}, Y 坐标:{y} , 当前角度: {int(angle)}")
if __name__ == '__main__':
center_x, center_y = 0, 0 # 记录剪裁滑块中心点在原图的位置
angle = 0
image_path = r"C:\Users\Administrator\Desktop\111\image.png" # 指定一个图片路径
path_dir = os.path.split(image_path)[0]
big_image_path = os.path.join(path_dir, 'path_to_cropped_image.png') # 大图像路径
small_image_path = os.path.join(path_dir, 'path_to_small_image.png') # 小图像路径
root = tkinter.Tk(className='滑块验证模拟')
image = Image.open(image_path)
photo = ImageTk.PhotoImage(image) # 将image转为tkinter可以显示的对象图片
width = root.winfo_screenwidth() # 获取屏幕宽度
height = root.winfo_screenheight() # 获取屏幕高度
image_width = image.width # 获取图片宽
image_height = image.height # 获取图片高
win_width = (width - image_width) // 2
win_height = (height - image_height) // 2
root.geometry(f'{image_width}x{image_height}+{win_width}+{win_height}') # 以图片大小创建窗口大小,并让窗口居中屏幕
crop_circle(image) # 切出大小图
label = tkinter.Label(root, text="鼠标坐标")
label.pack()
# 创建Canvas控件并显示大图
canvas = tkinter.Canvas(root, width=image_width, height=image_height)
canvas.pack()
big_image = tkinter.PhotoImage(file=big_image_path)
canvas.create_image(0, 0, anchor="nw", image=big_image)
# 显示小图
random_angle = random.randint(10, 350) # 随机一个角度,用于避免图片一加载就直接通过了
small_img = Image.open(small_image_path)
# 对图片进行随机旋转,center是旋转点坐标
rotated_image = small_img.rotate(random_angle, center=(small_img.width // 2, small_img.height // 2))
small_image = ImageTk.PhotoImage(rotated_image)
image_item = canvas.create_image(center_x-50, center_y-50, anchor="nw", image=small_image)
# 绑定鼠标单击事件
root.bind("<Motion>", update_coordinates)
canvas.bind("<B1-Motion>", on_click) # 鼠标按下拖动滑块
canvas.bind("<ButtonRelease-1>", func) # 鼠标松开检测是否重合
root.mainloop()