import os
import tkinter as tk
from tkinter import simpledialog, messagebox, filedialog
import cv2
import numpy as np
import os
import tkinter as tk
from tkinter import simpledialog, messagebox, filedialog
def get_video_path():
root = tk.Tk()
root.withdraw()
video_path = filedialog.askopenfilename(title='select video files', filetypes=[('video files', '*.mp4 *.avi')])
if not video_path:
print('no path input')
return None
return video_path
import cv2
def process_video_frames(video_path):
paused = False
cap = cv2.VideoCapture(video_path)
if not cap.isOpened():
print('Error: Unable to open video file')
return
frame_num = 0
while True:
ret, frame = cap.read()
if not ret:
break
frame_num += 1
# 转化为灰度
gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# 高斯模糊
gaussian_blur = cv2.GaussianBlur(gray_frame, (5, 5), 0)
# CLAHE 自适应直方图均衡化
clane = cv2.createCLAHE(clipLimit=3, tileGridSize=(9, 9))
clane_frame = clane.apply(gray_frame)
# 动态阈值 + Otsu 阈值
dynamics_threshold, ostu_frame = cv2.threshold(clane_frame, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
correct_threshold = dynamics_threshold
thresh_num, thresh_frame = cv2.threshold(clane_frame, correct_threshold, 255, cv2.THRESH_TOZERO_INV)
copy_frame = frame.copy()
# 找到轮廓
contours, _ = cv2.findContours(thresh_frame, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# 修改面积控制
min_area = 100 # 最小面积,增加过滤条件
max_area = 1000 # 最大面积,限制面积过大的噪声轮廓
centroids = []
for contour_index, contour in enumerate(contours):
area_contour = cv2.contourArea(contour)
if min_area < area_contour < max_area:
# 获取轮廓的外接矩形 (x, y, w, h)
x, y, w, h = cv2.boundingRect(contour)
moments = cv2.moments(contour)
cX = int(moments["m10"] / moments["m00"])
cY = int(moments["m01"] / moments["m00"])
centroids.append((cX,cY))
cv2.circle(copy_frame, (cX,cY), 10,(0,255,0), -1)
# 计算长宽比:取长边和短边的比值
long_side = max(w, h)
short_side = min(w, h)
aspect_ratio = long_side / short_side if short_side != 0 else 0
# 如果长宽比小于5,绘制轮廓
if aspect_ratio < 5:
# 绘制符合条件的轮廓
cv2.drawContours(copy_frame, [contour], -1, (0, 255, 0), 2)
cv2.rectangle(copy_frame, (x -10, y - 10), (x + w + 10, y + h + 10), (255,255,255), 2)
#cv2.putText(copy_frame, f'bubble{contour_index}', (x,y-20), cv2.FONT_HERSHEY_PLAIN, 1.7, (255,255,255), 2)
# 显示处理后的帧
cv2.imshow('frame with contour', copy_frame)
cv2.imshow('thresh frame', thresh_frame)
key = cv2.waitKey(1) & 0xFF
if key == ord('p'):
paused = not paused
if paused:
while paused:
key = cv2.waitKey(0) & 0xFF # 等待用户按键
if key == ord('p'):
paused = False
if key == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
video_path = get_video_path()
if video_path:
process_video_frames(video_path)
how can i filter bubbles accurately.