import csv
import cv2
import numpy as np
area_ratio = 80
enable_display = True
def on_slider(pos):
global area_ratio
area_ratio = pos
win_org = "original image"
win_value = "value image"
cap = cv2.VideoCapture("サンプル動画_気管支鏡.mp4")
if enable_display:
cv2.namedWindow(win_org, cv2.WINDOW_AUTOSIZE)
cv2.namedWindow(win_value, cv2.WINDOW_AUTOSIZE)
cv2.createTrackbar("area", win_org, area_ratio, 300, on_slider)
frame_count = 0
csv_data = []
while True:
# 画像読み込み
ret, frame = cap.read()
if not ret:
# break
cap.set(cv2.CAP_PROP_POS_FRAMES, 0)
frame_count = 0
print("rewind")
continue
# 輝度画像生成
hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
val_img = hsv[:, :, 2]
# 累積ヒストグラム算出
hist = cv2.calcHist([val_img], [0], None, [256], [0, 256])
# acc_hist = np.zeros(256, np.float32)
# acc_hist[0] = hist[0]
# しきい値決定
thres = -1
sum = 0
for i in range(0, 256):
sum += hist[i]
# acc_hist[i] = acc_hist[i - 1] + hist[i]
if thres < 0 and sum > (val_img.size * area_ratio / 1000):
thres = i
break
# 気道のマスク生成
val_img = cv2.GaussianBlur(val_img, (13, 13), 5.0)
mask = cv2.threshold(val_img, thres, 255, cv2.THRESH_BINARY_INV)[1]
# mask = cv2.threshold(val_img, area_ratio, 255, cv2.THRESH_BINARY_INV)[1]
# kernel = np.ones((5, 5), np.uint8)
# mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel)
retval, labels, stats, centroids = cv2.connectedComponentsWithStats(mask)
target_label = -1
min_dist = 0
center = [frame.shape[1] / 2, frame.shape[0] / 2]
# print([stats[i, cv2.CC_STAT_AREA] for i in range(retval)])
if retval > 1:
for i in range(1, retval):
dist = np.linalg.norm(centroids[i] - center, 2)
if stats[i, cv2.CC_STAT_AREA] > 200 and (
dist < min_dist or target_label < 0
):
min_dist = dist
target_label = i
selected_mask = np.zeros(mask.shape, np.uint8)
selected_mask[labels == target_label] = 255
contours, hierarchy = cv2.findContours(
selected_mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE
)
etime = frame_count * 1.0 / 30.0
cv2.putText(
frame,
"frame%4d time %.3fs" % (frame_count, etime),
(10, 25),
cv2.FONT_HERSHEY_TRIPLEX,
0.7,
(255, 0, 0),
1,
)
cv2.putText(
frame,
"area ratio=%.1f %%" % (area_ratio / 10),
(10, 50),
cv2.FONT_HERSHEY_TRIPLEX,
0.7,
(255, 0, 0),
1,
)
if len(contours) > 0:
# for i in range(len(contours)):
cv2.drawContours(frame, contours, 0, (0, 255, 255), 3)
area = cv2.contourArea(contours[0])
perimeter = cv2.arcLength(contours[0], True)
if perimeter > 0:
circle_level = 4.0 * np.pi * area / (perimeter * perimeter)
else:
circle_level = 0
# print(circle_level)
cv2.putText(
frame,
"circle level=%.1f %%" % (circle_level * 100),
(10, 75),
cv2.FONT_HERSHEY_TRIPLEX,
0.7,
(255, 0, 0),
1,
)
cv2.putText(
hsv,
"threshold=%d" % (thres),
(10, 30),
cv2.FONT_HERSHEY_TRIPLEX,
0.7,
(0, 0, 0),
1,
)
# frame[labels == target_label] = [0, 0, 0]
# cv2.imwrite("output/cl_%04d.jpg" % frame_count, frame)
csv_data.append([frame_count, etime, area_ratio / 10, thres, circle_level * 100])
if enable_display:
cv2.imshow(win_org, frame)
cv2.imshow(win_value, hsv[:, :, 2])
if cv2.waitKey(30) & 0xFF == 27:
break
frame_count += 1
# with open("output/analysis.csv", "w", newline="") as f:
# writer = csv.writer(f)
# writer.writerow(
# ["frame", "time(s)", "area ratio(%)", "threshold", "circle level(%)"]
# )
# writer.writerows(csv_data)
cap.release()
cv2.destroyAllWindows()