import cv2
import numpy as np

# パラメータと設定
image_path = 'path_to_your_image.jpg' # 画像のパス
mask_center = (x_center, y_center) # マスクの中心座標
mask_radius = 5 # マスクの半径
gaussian_blur_size = (5, 5) # ガウシアンブラーのサイズ
canny_threshold1 = 50 # Cannyエッジ検出の低い閾値
canny_threshold2 = 150 # Cannyエッジ検出の高い閾値
hough_threshold = 50 # ハフ変換の閾値
min_line_length = 100 # ハフ変換で検出する線の最小長
max_line_gap = 10 # ハフ変換での線の最大間隔

def find_line_circle_intersections(center, radius, line):
    # 円弧と直線の交点を計算する関数
    x1, y1, x2, y2 = line[0]
    cx, cy = center
    r = radius

    # 直線の方程式のパラメータを計算
    dx, dy = x2 - x1, y2 - y1
    A = dx * dx + dy * dy
    B = 2 * (dx * (x1 - cx) + dy * (y1 - cy))
    C = (x1 - cx) * (x1 - cx) + (y1 - cy) * (y1 - cy) - r * r

    # 二次方程式 Ax^2 + Bx + C = 0 を解く
    det = B * B - 4 * A * C
    if A <= 0.0000001 or det < 0:
        # 交点なし
        return None
    elif det == 0:
        # 一つの交点
        t = -B / (2 * A)
        return [(x1 + t * dx, y1 + t * dy)]
    else:
        # 二つの交点
        t1 = (-B + np.sqrt(det)) / (2 * A)
        t2 = (-B - np.sqrt(det)) / (2 * A)
        return [(x1 + t1 * dx, y1 + t1 * dy), (x1 + t2 * dx, y1 + t2 * dy)]

# 画像の読み込み
original_image = cv2.imread(image_path)

# 円形マスクの作成と適用
mask = np.zeros_like(original_image)
cv2.circle(mask, mask_center, mask_radius, (255, 255, 255), -1)
masked_image = cv2.bitwise_and(original_image, mask)

# グレースケール変換とノイズ低減
gray_image = cv2.cvtColor(masked_image, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray_image, gaussian_blur_size, 0)

# Cannyエッジ検出
edges = cv2.Canny(blurred, canny_threshold1, canny_threshold2)

# ハフ変換による直線検出
lines = cv2.HoughLinesP(edges, 1, np.pi / 180, hough_threshold, min_line_length, max_line_gap)

# 最長の2つの直線の選択と描画
if lines is not None and len(lines) > 0:
    sorted_lines = sorted(lines, key=lambda l: np.sqrt((l[0][2] - l[0][0]) ** 2 + (l[0][3] - l[0][1]) ** 2), reverse=True)
    top_lines = sorted_lines[:min(2, len(sorted_lines))]

    for line in top_lines:
        for x1, y1, x2, y2 in line:
            cv2.line(masked_image, (x1, y1), (x2, y2), (0, 255, 0), 2)

    if len(top_lines) == 2:
        # 2本の直線の交点を計算するロジックを追加(前述のコード参照)
        pass
    elif len(top_lines) == 1:
        intersections = find_line_circle_intersections(mask_center, mask_radius, top_lines[0])
        if intersections is not None:
            # 最も遠い交点を選択
            farthest_point = max(intersections, key=lambda p: np.sqrt((p[0] - mask_center[0]) ** 2 + (p[1] - mask_center[1]) ** 2))
            cv2.line(masked_image, mask_center, (int(farthest_point[0]), int(farthest_point[1])), (0, 255, 0), 2)
else:
    print("直線無し")

cv2.imwrite('top_lines_image.jpg', masked_image)

# すべての線を描画して保存
all_lines_image = np.copy(original_image)
if lines is not None:
    for line in lines:
        for x1, y1, x2, y2 in line:
            cv2.line(all_lines_image, (x1, y1), (x2, y2), (255, 0, 0), 1)
cv2.imwrite('all_lines_image.jpg', all_lines_image)

# エッジを重ね合わせた画像を保存
edge_highlighted = np.copy(original_image)
edge_highlighted[edges != 0] = [0, 0, 255]
cv2.imwrite('edge_overlayed_image.jpg', edge_highlighted)

# 結果の表示
cv2.imshow('Top Lines Image', masked_image)
cv2.imshow('All Lines Image', all_lines_image)
cv2.imshow('Edge Overlay Image', edge_highlighted)
cv2.waitKey(0)
cv2.destroyAllWindows()