106 lines
3.9 KiB
Python
106 lines
3.9 KiB
Python
|
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)
|
|||
|
# 檢測直線
|
|||
|
lines = cv2.HoughLinesP(edges, 1, np.pi / 180, threshold=100, minLineLength=100, maxLineGap=200)
|
|||
|
|
|||
|
# 初始化黑色圖像
|
|||
|
black_img = gray_image.copy()
|
|||
|
black_img[:, :] = 0
|
|||
|
|
|||
|
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(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
|
|||
|
|
|||
|
# 計算直徑
|
|||
|
self.calculate_diameter(300, x_list, y_list, pixel_size_um)
|
|||
|
self.calculate_diameter(o_img_black.shape[1] - 300, x_list, y_list, pixel_size_um)
|
|||
|
|
|||
|
# 計算角度並找到負角度的最小值和正角度的最大值
|
|||
|
self.calculate_angles(lines)
|
|||
|
|
|||
|
# 標記相交點
|
|||
|
self.mark_intersection_points(o_img_black, x_list, y_list, 300, o_img_black.shape[1] - 300)
|
|||
|
|
|||
|
# 顯示結果
|
|||
|
self.display_image(o_img_black)
|
|||
|
|
|||
|
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")
|
|||
|
|
|||
|
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} °")
|
|||
|
|
|||
|
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, (255, 0, 0), -1)
|
|||
|
|
|||
|
for i in range(len(x_list)):
|
|||
|
point = (x_list[i], y_list[i])
|
|||
|
cv2.circle(img, point, 1, (0, 255, 0), -1)
|
|||
|
|
|||
|
def display_image(self, img):
|
|||
|
resized_img = cv2.resize(img, (1080, 1080))
|
|||
|
cv2.imshow('Processed Image', resized_img)
|
|||
|
cv2.waitKey(0)
|
|||
|
cv2.destroyAllWindows()
|
|||
|
|
|||
|
|
|||
|
if __name__ == "__main__":
|
|||
|
image_path = r'D:\Code\Project\Medeologix\Python\Size\01_10fps_0.041ms_0db_1092\01.bmp'
|
|||
|
processor = ImageProcessor(image_path)
|