今回大変投げつけな質問になってしまうかもしれなく申し訳ないのですが
今天井に全方位カメラを設置し、人が倒れたことを検出するプログラムを書いているのですが
方法としては背景差分法を用いて二値化画像にして人の輪郭を抽出し、重心から底辺までの距離の長さの変化で転倒を検知するというものなのですが、うまく背景差分法で人の輪郭を抽出できません。動いているとところどころ背景とかぶってしまったり、影?ができてしまい大きさを一定に保てません。もし改善点などありましたら何卒教えていただきたいと思っています。
python
1コード 2#coding:utf-8 3 4import numpy as np 5import cv2 6import math 7import matplotlib.pyplot as plt 8import itertools 9import csv 10 11 12cap = cv2.VideoCapture('turn.mp4') 13 14 15 16#背景差分法のアルゴリズム 17#fgbg = cv2.createBackgroundSubtractorKNN(detectShadows = True) 18#fgbg = cv2.bgsegm.createBackgroundSubtractorMOG() 19#fgbg = cv2.createBackgroundSubtractorMOG2() 20fgbg = cv2.bgsegm.createBackgroundSubtractorGSOC() 21 22 23 24 25 26def End_point(cnt): 27 28 total = [] 29 dict = {} 30 31 topmost = tuple(cnt[cnt[:,:,1].argmin()][0]) 32 bottommost = tuple(cnt[cnt[:,:,1].argmax()][0]) 33 leftmost = tuple(cnt[cnt[:,:,0].argmin()][0]) 34 rightmost = tuple(cnt[cnt[:,:,0].argmax()][0]) 35 36 37 #輪郭の重心 38 mu = cv2.moments(cnt) 39 x,y= int(mu["m10"]/mu["m00"]) , int(mu["m01"]/mu["m00"]) 40 cv2.circle(frame, (x,y), 5, (255,255,255), -1) 41 42 x1,y1 = topmost 43 x2,y2 = bottommost 44 x3,y3 = leftmost 45 x4,y4 = rightmost 46 47 48 49 #重心から端点までの距離計算 50 head = y - y1 51 leg = y2 - y1 52 left = x-x3 53 right = x4 -x 54 55 56 total.append(head) 57 total.append(leg) 58 total.append(left) 59 total.append(right) 60 61 62 63 #輪郭の端点をソートする 64 total.sort() 65 66 #辞書に追加 67 dict[total[1]] = topmost 68 dict[total[0]] = bottommost 69 dict[total[2]] = leftmost 70 dict[total[3]] = rightmost 71 72 #要素を取り出す 73 total1 = dict[total[1]] 74 total2 = dict[total[0]] 75 total3 = dict[total[2]] 76 total4 = dict[total[3]] 77 78 #ソートから距離線を描画 79 x5,y5 = total1 80 x6,y6 = total2 81 82 83 #頂点から底辺 84 cv2.line(frame,total1, total2,(0,0,0),3) 85 #print("縦の長さ",total[0]+total[1]) 86 87 cv2.line(frame,(x,y), leftmost,(255,255,255),3) 88 #print(left) 89 #print("重心から頭までの距離 = ",head) 90 #print("重心から足までの距離 = ",leg) 91 #print(head_leg) 92 93 print(total[1]+total[0]) 94 95 96 97 dict.clear() 98 99 100while (cap.isOpened()): 101 102 ret, frame = cap.read() 103 104 im_size = (600,600) 105 106 frame = cv2.resize(frame,im_size) 107 108 109 #グレースケール 110 gray = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY) 111 112 #ガウシアンフィルタ 113 blur = cv2.GaussianBlur(gray,(5,5),0) 114 115 #背景差分 116 fgmask= fgbg.apply(blur) 117 118 #2値化処理 119 ret,dilation = cv2.threshold(fgmask,0,200,cv2.THRESH_BINARY) 120 121 #カーネル 122 kernel = np.ones((7,7),np.uint8) 123 124 #モルフォロジー変換 125 dilation = cv2.dilate(dilation,kernel,iterations = 4) 126 dilation = cv2.erode(dilation,kernel,iterations = 4) 127 128 #輪郭抽出 129 imge, contours, hierarch=cv2.findContours(dilation,cv2.RETR_LIST,cv2.CHAIN_APPROX_NONE) 130 131 max_area_contour=-1 132 max_area = 0 133 134 # 各輪郭に対する処理 135 for contour in contours: 136 137 # 輪郭の領域を計算 138 area = cv2.contourArea(contour) 139 140 #最大面積を計算 141 maxCont=contours[0] 142 for contour in contours: 143 if len(maxCont)<len(contour): 144 maxCont=contour 145 146 # ノイズ(小さすぎる領域)と全体の輪郭(大きすぎる領域)を除外 147 if area< 1e2 or 1e5 < area: 148 continue 149 150 #輪郭描画 151 cv2.drawContours(frame,[maxCont], 0, (255,255,255), 3) 152 153 154 #輪郭の端点を抽出 155 End_point(maxCont) 156 157 #print(int(timer),"秒経過しました") 158 159 #表示 160 cv2.imshow('1',frame) 161 cv2.imshow('frame',dilation) 162 163 if cv2.waitKey(30) & 0xff == ord('q'): 164 break 165 166cap.release() 167cv2.destroyAllWindows() 168
あなたの回答
tips
プレビュー