MacOS 10.13.4平台Python3 ECG扫描图间隔测量GUI开发需求
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
Pillowhandles image loading/saving and clean rotationsOpenCVhelps detect the baseline angle via line detectionNumPysupports numerical operations for image processingTkinteris 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:
Cannyedge detection makes the ECG’s thin baseline lines stand out for easier detectionHoughLinesfinds 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
rotatewithexpand=Trueensures 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
pip3instead ofpipto 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
HoughLinesthreshold (the200value) 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

