You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MacOS 10.13.4平台Python3 ECG扫描图间隔测量GUI开发需求

ECG Image Rotation for Your Python GUI Tool (macOS 10.13.4)

Hey there! Let’s walk through how to build the baseline-rotation feature for your ECG measurement tool. Since you’re on macOS 10.13.4 with basic Python skills (no pro dev background required), we’ll stick to accessible, well-documented libraries that play nicely with your setup.

Step 1: Install Required Libraries

First, let’s get the tools we need. Open your terminal and run these commands (we’re picking versions compatible with macOS 10.13.4 to avoid compatibility headaches):

pip3 install pillow==9.5.0 opencv-python==4.5.5.62 numpy==1.21.6
  • Pillow handles image loading/saving and clean rotations
  • OpenCV helps detect the baseline angle via line detection
  • NumPy supports numerical operations for image processing
  • Tkinter is Python’s built-in GUI toolkit (no extra install needed for most Python3 setups on macOS)

Step 2: Core Rotation Logic (Find & Fix Baseline Angle)

The key here is detecting the angle of the ECG’s baseline, then rotating the image to make it perfectly horizontal. Here’s a simplified, commented code snippet to test this logic first:

import cv2
import numpy as np
from PIL import Image

def rotate_ecg_to_baseline(image_path):
    # Load image with OpenCV
    img = cv2.imread(image_path)
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    
    # Edge detection to highlight ECG lines (adjust thresholds if needed)
    edges = cv2.Canny(gray, 50, 150, apertureSize=3)
    
    # Detect straight lines using Hough Transform
    lines = cv2.HoughLines(edges, 1, np.pi/180, 200)
    
    # Calculate angles of detected near-horizontal lines (our baseline candidates)
    angles = []
    if lines is not None:
        for rho, theta in lines[:, 0]:
            angle = np.degrees(theta)
            # Filter for lines close to horizontal (80-100 degrees)
            if 80 < angle < 100:
                angles.append(angle)
    
    # Determine rotation angle (use median to avoid outliers)
    if angles:
        median_angle = np.median(angles)
        # Calculate how much to rotate to make baseline 0 degrees (horizontal)
        rotation_angle = 90 - median_angle if median_angle > 90 else -(90 - median_angle)
    else:
        # Fallback: if no lines detected, assume no rotation needed
        rotation_angle = 0
    
    # Rotate with Pillow to avoid cropping and fill empty space with white (matches ECG paper)
    pil_img = Image.open(image_path)
    rotated_img = pil_img.rotate(rotation_angle, expand=True, fillcolor="white")
    
    return rotated_img

# Test the function with your ECG scan
if __name__ == "__main__":
    rotated = rotate_ecg_to_baseline("your_ecg_scan.png")
    rotated.save("rotated_ecg.png")
    rotated.show()

Quick Notes on the Logic:

  • Canny edge detection makes the ECG’s thin baseline lines stand out for easier detection
  • HoughLines finds all straight lines; we filter for near-horizontal ones since that’s where the baseline lives
  • Using the median angle instead of average ignores random noise or outlier lines (like lead wires)
  • Pillow’s rotate with expand=True ensures the entire rotated image stays visible, no cropping

Step 3: Wrap It in a Simple Tkinter GUI

Now let’s turn this logic into a user-friendly GUI so you can upload, rotate, and save ECG images without touching the terminal. Here’s a minimal example:

import tkinter as tk
from tkinter import filedialog, Label, Button
from PIL import Image, ImageTk

class ECGRotatorGUI:
    def __init__(self, root):
        self.root = root
        self.root.title("ECG Baseline Rotator")
        
        # UI Buttons
        self.upload_btn = Button(root, text="Upload ECG Image", command=self.upload_image)
        self.upload_btn.pack(pady=10)
        
        self.rotate_btn = Button(root, text="Rotate to Baseline", command=self.rotate_image, state=tk.DISABLED)
        self.rotate_btn.pack(pady=5)
        
        self.save_btn = Button(root, text="Save Rotated Image", command=self.save_image, state=tk.DISABLED)
        self.save_btn.pack(pady=5)
        
        # Image display labels
        self.original_label = Label(root, text="Original Image")
        self.original_label.pack(pady=5)
        
        self.rotated_label = Label(root, text="Rotated Image")
        self.rotated_label.pack(pady=5)
        
        # Store loaded images
        self.original_img = None
        self.rotated_img = None
    
    def upload_image(self):
        file_path = filedialog.askopenfilename(filetypes=[("Image Files", "*.png *.jpg *.jpeg")])
        if file_path:
            self.original_img = Image.open(file_path)
            # Resize for display (adjust dimensions as needed)
            display_img = self.original_img.resize((400, 300))
            tk_img = ImageTk.PhotoImage(display_img)
            self.original_label.config(image=tk_img, text="")
            self.original_label.image = tk_img  # Keep reference to avoid garbage collection
            
            self.rotate_btn.config(state=tk.NORMAL)
    
    def rotate_image(self):
        if self.original_img:
            # Save temp copy to use our rotation function
            temp_path = "temp_ecg.png"
            self.original_img.save(temp_path)
            self.rotated_img = rotate_ecg_to_baseline(temp_path)
            
            # Display rotated image
            display_rotated = self.rotated_img.resize((400, 300))
            tk_rotated = ImageTk.PhotoImage(display_rotated)
            self.rotated_label.config(image=tk_rotated, text="")
            self.rotated_label.image = tk_rotated
            
            self.save_btn.config(state=tk.NORMAL)
    
    def save_image(self):
        if self.rotated_img:
            save_path = filedialog.asksaveasfilename(defaultextension=".png", filetypes=[("PNG Files", "*.png"), ("JPEG Files", "*.jpg")])
            if save_path:
                self.rotated_img.save(save_path)

# Launch the GUI
if __name__ == "__main__":
    root = tk.Tk()
    app = ECGRotatorGUI(root)
    root.mainloop()

Tips for Your macOS 10.13.4 Setup

  • Use pip3 instead of pip to ensure you’re targeting Python3 (easy to mix up on macOS)
  • If library installs fail, double-check you’re using the version numbers listed—newer versions may not support older macOS releases
  • Test with a few scans first: if rotation isn’t perfect, tweak the HoughLines threshold (the 200 value) or angle filter (80-100 degrees) to match your specific ECG scans

Since you have basic Python skills, you can iterate on this easily: add error handling for broken images, tweak the UI layout, or later integrate this with your ECG interval measurement logic.

内容的提问来源于stack exchange,提问作者ecjb

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 10:22:13