当前位置: 首页 > news >正文

搞了搞Python,写了个图片对比程序及AI硅基流动对话

图片对比(查重图片)

import tkinter as tk
from tkinter import filedialog, messagebox
from PIL import Image, ImageTk
from docx import Document
import io
import zipfile
import xml.etree.ElementTree as ET
import xxhash
from concurrent.futures import ThreadPoolExecutor


same_images = []  # 存储相同图片的信息
current_index = 0  # 当前显示的图片索引

def extract_images_with_positions(docx_file):
    doc = Document(docx_file)
    images = []
    with zipfile.ZipFile(docx_file) as z:
        with z.open('word/document.xml') as f:
            xml_content = f.read()
            root = ET.fromstring(xml_content)
        namespace = {
            'w': 'http://schemas.openxmlformats.org/wordprocessingml/2006/main',
            'a': 'http://schemas.openxmlformats.org/drawingml/2006/main',
            'r': 'http://schemas.openxmlformats.org/officeDocument/2006/relationships'
        }
        for i, para in enumerate(root.findall('.//w:p', namespace)):
            for drawing in para.findall('.//w:drawing', namespace):
                blip = drawing.find('.//a:blip', namespace)
                if blip is not None:
                    rId = blip.attrib.get('{http://schemas.openxmlformats.org/officeDocument/2006/relationships}embed')
                    if rId:
                        img_data = doc.part.related_parts[rId].blob
                        page_number = (i // 10) + 1
                        images.append({
                            "data": img_data,
                            "position": f"段落 {i + 1}",
                            "page": f"第 {page_number} 页"
                        })
    return images

def image_hash(image_data):
    return xxhash.xxh64(image_data).hexdigest()

def compare_images(docx1, docx2):
    with ThreadPoolExecutor() as executor:
        future1 = executor.submit(extract_images_with_positions, docx1)
        future2 = executor.submit(extract_images_with_positions, docx2)
        images1 = future1.result()
        images2 = future2.result()

    same_images = []
    hash_cache = {}  

    for img1 in images1:
        if img1["data"] not in hash_cache:
            hash_cache[img1["data"]] = image_hash(img1["data"])
        hash1 = hash_cache[img1["data"]]

        for img2 in images2:
            if img2["data"] not in hash_cache:
                hash_cache[img2["data"]] = image_hash(img2["data"])
            hash2 = hash_cache[img2["data"]]

            if hash1 == hash2:
                same_images.append({
                    "image1_data": img1["data"],
                    "image1_position": img1["position"],
                    "image1_page": img1["page"],
                    "image2_data": img2["data"],
                    "image2_position": img2["position"],
                    "image2_page": img2["page"]
                })
                break

    return same_images

def open_file(entry):
    file_path = filedialog.askopenfilename(filetypes=[("Word files", "*.docx")])
    entry.delete(0, tk.END)
    entry.insert(0, file_path)

def clear_display():
    label_img1.config(image=None)
    label_img1.image = None
    label_img2.config(image=None)
    label_img2.image = None
    label_position1.config(text="")
    label_position2.config(text="")
    page_label.config(text="")

def show_images(index):
    if not same_images:
        return
    image_info = same_images[index]
    img1 = Image.open(io.BytesIO(image_info["image1_data"]))
    img1 = img1.resize((250, 250), Image.ANTIALIAS)
    img1_tk = ImageTk.PhotoImage(img1)
    label_img1.config(image=img1_tk)
    label_img1.image = img1_tk  
    img2 = Image.open(io.BytesIO(image_info["image2_data"]))
    img2 = img2.resize((250, 250), Image.ANTIALIAS)
    img2_tk = ImageTk.PhotoImage(img2)
    label_img2.config(image=img2_tk)
    label_img2.image = img2_tk 

    label_position1.config(text=f"文件1位置: {image_info['image1_position']} ({image_info['image1_page']})")
    label_position2.config(text=f"文件2位置: {image_info['image2_position']} ({image_info['image2_page']})")

    page_label.config(text=f"第 {index + 1} 张 / 共 {len(same_images)} 张")

def show_enlarged_image(image_data):
    img = Image.open(io.BytesIO(image_data))
    img_tk = ImageTk.PhotoImage(img)

    enlarge_window = tk.Toplevel()
    enlarge_window.title("放大图片")

    label_enlarged = tk.Label(enlarge_window, image=img_tk)
    label_enlarged.pack()

    label_enlarged.image = img_tk

def next_image():
    global current_index
    if current_index < len(same_images) - 1:
        current_index += 1
        show_images(current_index)

def prev_image():
    global current_index
    if current_index > 0:
        current_index -= 1
        show_images(current_index)

def compare_button_click():
    global same_images, current_index
    file1 = entry_file1.get()
    file2 = entry_file2.get()

    if not file1 or not file2:
        messagebox.showwarning("警告", "请选择两个DOCX文件")
        return

    clear_display()

    same_images = compare_images(file1, file2)
    current_index = 0

    if not same_images:
        result_label.config(text="没有找到相同的图片")
    else:
        result_label.config(text=f"找到 {len(same_images)} 张相同的图片")
        show_images(current_index)

root = tk.Tk()
root.title("DOCX图片对比工具")

frame_files = tk.Frame(root)
frame_files.pack(pady=10)

label_file1 = tk.Label(frame_files, text="文件1:")
label_file1.grid(row=0, column=0, padx=5, pady=5)
entry_file1 = tk.Entry(frame_files, width=40)
entry_file1.grid(row=0, column=1, padx=5, pady=5)
button_file1 = tk.Button(frame_files, text="选择文件", command=lambda: open_file(entry_file1))
button_file1.grid(row=0, column=2, padx=5, pady=5)

label_file2 = tk.Label(frame_files, text="文件2:")
label_file2.grid(row=1, column=0, padx=5, pady=5)
entry_file2 = tk.Entry(frame_files, width=40)
entry_file2.grid(row=1, column=1, padx=5, pady=5)
button_file2 = tk.Button(frame_files, text="选择文件", command=lambda: open_file(entry_file2))
button_file2.grid(row=1, column=2, padx=5, pady=5)

compare_button = tk.Button(root, text="对比图片", command=compare_button_click)
compare_button.pack(pady=10)

result_label = tk.Label(root, text="")
result_label.pack(pady=10)

frame_images = tk.Frame(root)
frame_images.pack(pady=10)

frame_image1 = tk.Frame(frame_images)
frame_image1.grid(row=0, column=0, padx=10)
label_img1 = tk.Label(frame_image1, text="文件1图片")
label_img1.pack()
label_position1 = tk.Label(frame_image1, text="")
label_position1.pack()

frame_image2 = tk.Frame(frame_images)
frame_image2.grid(row=0, column=1, padx=10)
label_img2 = tk.Label(frame_image2, text="文件2图片")
label_img2.pack()
label_position2 = tk.Label(frame_image2, text="")
label_position2.pack()

frame_navigation = tk.Frame(root)
frame_navigation.pack(pady=10)

prev_button = tk.Button(frame_navigation, text="上一张", command=prev_image)
prev_button.grid(row=0, column=0, padx=5)

next_button = tk.Button(frame_navigation, text="下一张", command=next_image)
next_button.grid(row=0, column=1, padx=5)

page_label = tk.Label(root, text="")
page_label.pack(pady=10)

root.mainloop()

AI聊天

import tkinter as tk
from tkinter import scrolledtext, ttk
import requests
import threading

API_URL = "https://api.siliconflow.cn/v1/chat/completions"
API_KEY = "sk-kqfjwpreepqitvsvhpipjvnscnxqadsuomiaaflkmmxsghps"  # 替换为你的 API Key

root = tk.Tk()
root.title("硅基流动 AI 聊天框")
root.geometry("600x700")

chat_box = scrolledtext.ScrolledText(root, wrap=tk.WORD, state='disabled', font=("Arial", 12))
chat_box.pack(padx=10, pady=10, fill=tk.BOTH, expand=True)

input_frame = tk.Frame(root)
input_frame.pack(padx=10, pady=10, fill=tk.X)

model_label = tk.Label(input_frame, text="模型名称:", font=("Arial", 12))
model_label.pack(side=tk.LEFT, padx=(0, 10))

model_var = tk.StringVar(value="Qwen/Qwen2.5-7B-Instruct")  # 默认模型名称
model_entry = tk.Entry(input_frame, textvariable=model_var, width=20, font=("Arial", 12))
model_entry.pack(side=tk.LEFT, padx=(0, 10))

user_input = tk.Entry(input_frame, width=30, font=("Arial", 12))
user_input.pack(side=tk.LEFT, fill=tk.X, expand=True)

send_button = tk.Button(input_frame, text="发送", command=lambda: send_message(), font=("Arial", 12))
send_button.pack(side=tk.RIGHT, padx=(10, 0))

params_frame = tk.Frame(root)
params_frame.pack(padx=10, pady=10, fill=tk.X)

max_tokens_label = tk.Label(params_frame, text="max_tokens:", font=("Arial", 12))
max_tokens_label.pack(side=tk.LEFT, padx=(0, 10))

max_tokens_var = tk.IntVar(value=512)  
max_tokens_entry = tk.Entry(params_frame, textvariable=max_tokens_var, width=10, font=("Arial", 12))
max_tokens_entry.pack(side=tk.LEFT, padx=(0, 10))

temperature_label = tk.Label(params_frame, text="temperature:", font=("Arial", 12))
temperature_label.pack(side=tk.LEFT, padx=(0, 10))

temperature_var = tk.DoubleVar(value=0.7)  
temperature_entry = tk.Entry(params_frame, textvariable=temperature_var, width=10, font=("Arial", 12))
temperature_entry.pack(side=tk.LEFT, padx=(0, 10))

def display_message(sender, message):
    chat_box.config(state='normal')
    chat_box.insert(tk.END, f"{sender}: {message}\n\n")
    chat_box.config(state='disabled')
    chat_box.yview(tk.END)

def send_message():
    message = user_input.get().strip()
    if not message:
        return

    display_message("你", message)
    user_input.delete(0, tk.END)

    selected_model = model_var.get()
    max_tokens = max_tokens_var.get()
    temperature = temperature_var.get()

    threading.Thread(target=fetch_ai_response, args=(selected_model, message, max_tokens, temperature)).start()

def fetch_ai_response(model, message, max_tokens, temperature):
    try:
        headers = {
            "Content-Type": "application/json",
            "Authorization": f"Bearer {API_KEY}"
        }
        data = {
            "model": model,  # 动态传入模型名称
            "messages": [{"role": "user", "content": message}],
            "stream": False,
            "max_tokens": max_tokens,
            "temperature": temperature,
            "top_p": 0.7,
            "top_k": 50,
            "frequency_penalty": 0.5,
            "response_format": {"type": "text"}
        }
        print("Sending request to:", API_URL)
        print("Headers:", headers)
        print("Body:", data)
        response = requests.post(API_URL, headers=headers, json=data)
        response.raise_for_status()
        result = response.json()
        print("Received response:", result)

        ai_response = result.get("choices", [{}])[0].get("message", {}).get("content", "抱歉,我暂时无法处理你的请求。")
        display_message("AI", ai_response)
    except requests.exceptions.HTTPError as e:
        print(f"HTTP Error: {e}")
        print(f"Response content: {e.response.text}")  
        display_message("AI", "抱歉,我暂时无法处理你的请求。")
    except Exception as e:
        print(f"Error fetching AI response: {e}")
        display_message("AI", "抱歉,我暂时无法处理你的请求。")

root.bind('<Return>', lambda event: send_message())

root.mainloop()

相关文章:

  • BFF与API Gateway的区别解析
  • Socket 、WebSocket、Socket.IO详细对比
  • Dify 搭建
  • 智能汽车图像及视频处理方案,支持视频智能包装创作能力
  • koupleless 合并多个微服务应用到一个应用实例(包含springcloud gateway)
  • w259交通管理在线服务系统设计与实现
  • Nginx限流与鉴权(Nginx Traffic Limiting and Authentication)
  • JS逆向:泛微OA的前端密码加密逆向分析,并使用Python构建泛微OA登录
  • [023-01-47].第47节:组件应用 - GetWay与 Sentinel 集成实现服务限流
  • 3.17学习总结 java数组
  • Compose 实践与探索十四 —— 自定义布局
  • 第四章 搜索基础
  • python项目一键加密,极度简洁
  • 【嵌入式硬件】三款DCDC调试笔记
  • 华为OD机试 - 德州扑克 - 逻辑分析(Java 2023 B卷 200分)
  • fastapi+angular外卖系统
  • 数据结构——图
  • 【笔记】SQL进阶教程(第二版)
  • Word 小黑第22套
  • 在动平衡中倒谱(Cepstrum)
  • 98年服装“厂二代”:关税压力下,我仍相信中国供应链|湃客Talk
  • 中国海警依法驱离日非法进入我钓鱼岛领海船只
  • 复旦设立新文科发展基金,校友曹国伟、王长田联合捐赠1亿元
  • 万里云端遇见上博--搭乘“上博号”主题飞机体验记
  • 抗战回望20︱《山西省战区抗敌行政工作检讨会议议决案》:“强民政治”、“说服行政”
  • A股三大股指集体高开大涨超1%,券商、房地产涨幅居前