medical_balloon/Dimensional_Inspection/size_0625_test.py

147 lines
6.6 KiB
Python
Raw Normal View History

2024-07-30 16:18:26 +08:00
import cv2
import numpy as np
class ImageProcessor:
def __init__(self, image_path):
# 讀取圖像
self.original_image = cv2.imread(image_path)
self.process_image()
def process_image(self):
# 複製原始圖像
img = self.original_image.copy()
o_img_black = img.copy()
o_img_black[:, :, :] = 0
# 將圖像轉換為灰度圖
gray_image = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 使用 Canny 邊緣檢測
edges = cv2.Canny(gray_image, 250, 250)
cv2.imshow('Canny Edges', edges) # 顯示 Canny 邊緣檢測結果
cv2.imwrite('canny_edges.jpg', edges) # 保存 Canny 邊緣檢測結果
# 檢測直線
lines = cv2.HoughLinesP(edges, 1, np.pi / 180, threshold=100, minLineLength=100, maxLineGap=200)
# 初始化黑色圖像
black_img = gray_image.copy()
black_img[:, :] = 0
hough_lines_image = black_img.copy() # 用於顯示HoughLinesP檢測結果的圖像
if lines is not None:
for line in lines:
x1, y1, x2, y2 = line[0]
cv2.line(black_img, (x1, y1), (x2, y2), (255, 255, 0), 2)
cv2.line(hough_lines_image, (x1, y1), (x2, y2), (255, 255, 0), 2)
cv2.imshow('Hough Lines', hough_lines_image) # 顯示 HoughLinesP 檢測結果
cv2.imwrite('hough_lines.jpg', hough_lines_image) # 保存 HoughLinesP 檢測結果
# 繪製紅色的兩條線
cv2.line(o_img_black, (300, 0), (300, len(o_img_black)), (0, 0, 255), 2)
cv2.line(o_img_black, (len(o_img_black[0]) - 300, 0), (len(o_img_black[0]) - 300, len(o_img_black)), (0, 0, 255), 2)
# 找到黑色圖像中白色255的像素
y_list, x_list = np.where(black_img == 255)
# 像素大小5.5um
pixel_size_um = 5.5
# 計算直徑
diameter1, point1_top, point1_bottom = self.calculate_diameter(300, x_list, y_list, pixel_size_um)
diameter2, point2_top, point2_bottom = self.calculate_diameter(o_img_black.shape[1] - 300, x_list, y_list, pixel_size_um)
# 計算角度並找到負角度的最小值和正角度的最大值
angle_sum = self.calculate_angles(lines)
# 標記相交點
self.mark_intersection_points(o_img_black, x_list, y_list, 300, o_img_black.shape[1] - 300)
# 繪製點和垂直線
self.draw_points_and_lines(diameter1, diameter2, point1_top, point1_bottom, point2_top, point2_bottom)
# 顯示結果
self.display_image(o_img_black, diameter1, diameter2, angle_sum)
def calculate_diameter(self, x_value, x_list, y_list, pixel_size_um):
indices = np.where(x_list == x_value)[0]
y_values = y_list[indices]
max_y = np.max(y_values)
min_y = np.min(y_values)
diff = max_y - min_y
diameter = diff * pixel_size_um / 1000
print(f"直徑: Ø{diameter:.3f} mm")
return diameter, (x_value, min_y), (x_value, max_y)
def calculate_angles(self, lines):
min_negative_angle = float('inf')
max_positive_angle = float('-inf')
if lines is not None:
for line in lines:
x1, y1, x2, y2 = line[0]
angle = np.arctan2(y2 - y1, x2 - x1) * 180.0 / np.pi
if angle < 0:
min_negative_angle = min(min_negative_angle, angle)
elif angle > 0:
max_positive_angle = max(max_positive_angle, angle)
if min_negative_angle != float('inf') and max_positive_angle != float('-inf'):
min_negative_angle_abs = abs(min_negative_angle)
angle_sum = min_negative_angle_abs + max_positive_angle
print(f"角度為: {angle_sum:.2f} °")
return angle_sum
return None
def mark_intersection_points(self, img, x_list, y_list, x_value1, x_value2):
indices_1 = np.where(x_list == x_value1)[0]
indices_2 = np.where(x_list == x_value2)[0]
intersection_points_1 = [(x_value1, y_list[i]) for i in indices_1]
intersection_points_2 = [(x_value2, y_list[i]) for i in indices_2]
intersection_points = intersection_points_1 + intersection_points_2
for point in intersection_points:
cv2.circle(img, point, 10, (183, 143, 58), -1)
for i in range(len(x_list)):
point = (x_list[i], y_list[i])
cv2.circle(img, point, 1, (183, 143, 58), -1)
def draw_points_and_lines(self, diameter1, diameter2, point1_top, point1_bottom, point2_top, point2_bottom):
# 在原圖上添加測量點和連接線
cv2.line(self.original_image, point1_top, point1_bottom, (121, 180, 177), 2)
cv2.circle(self.original_image, point1_top, 10, (183, 143, 58), -1)
cv2.circle(self.original_image, point1_bottom, 10, (183, 143, 58), -1)
cv2.line(self.original_image, point2_top, point2_bottom, (121, 180, 177), 2)
cv2.circle(self.original_image, point2_top, 10, (183, 143, 58), -1)
cv2.circle(self.original_image, point2_bottom, 10, (183, 143, 58), -1)
def display_image(self, img, diameter1, diameter2, angle_sum):
# Resize and display original image
original_resized = cv2.resize(self.original_image, (1280, 1280))
# Add status bar information on the original image
cv2.putText(original_resized, f"Diameter1: {diameter1:.3f} mm", (25, 80), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 0), 2) #300
cv2.putText(original_resized, f"Diameter2: {diameter2:.3f} mm", (25, 130), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 0), 2) #350
# cv2.putText(original_resized, f"Diameter1: {diameter1:.3f} mm", (25, 100), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 0), 2)
# cv2.putText(original_resized, f"Diameter2: {diameter2:.3f} mm", (25, 150), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 0), 2)
if angle_sum is not None:
cv2.putText(original_resized, f"Angle: {angle_sum:.2f} degrees", (25, 180), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 0), 2) #400
# Resize and display processed image
processed_resized = cv2.resize(img, (1280, 1280))
# Show the images
cv2.imshow('Original Image', original_resized)
cv2.imwrite('Original_Image.jpg', original_resized) # 保存 original 邊緣檢測結果
cv2.imshow('Processed Image', processed_resized)
cv2.imwrite('Processed_Image.jpg', processed_resized) # 保存 Processed 邊緣檢測結果
cv2.waitKey(0)
cv2.destroyAllWindows()
if __name__ == "__main__":
image_path = r'D:\Code\Project\Medeologix\Python\Size\01_10fps_0.041ms_0db_1092\10.bmp'
processor = ImageProcessor(image_path)