├── Images ├── Readme.md ├── pipeline1.png ├── pipeline2.png └── pipeline3.png ├── change.npy ├── bounds1.npy ├── bounds2.npy ├── centers1.npy ├── centers2.npy ├── result1.npy ├── result2.npy ├── Result.txt ├── Masks ├── Readme.md └── get_ignore_area.py ├── extract_processed.py ├── extract_frames.py ├── README.md ├── Seg_masks.py ├── Detector.py ├── Seg_masks.ipynb ├── Detector.ipynb └── vid_utils.py /Images/Readme.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /change.npy: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevaldoshi17/NVIDIA_AICITY/HEAD/change.npy -------------------------------------------------------------------------------- /bounds1.npy: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevaldoshi17/NVIDIA_AICITY/HEAD/bounds1.npy -------------------------------------------------------------------------------- /bounds2.npy: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevaldoshi17/NVIDIA_AICITY/HEAD/bounds2.npy -------------------------------------------------------------------------------- /centers1.npy: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevaldoshi17/NVIDIA_AICITY/HEAD/centers1.npy -------------------------------------------------------------------------------- /centers2.npy: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevaldoshi17/NVIDIA_AICITY/HEAD/centers2.npy -------------------------------------------------------------------------------- /result1.npy: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevaldoshi17/NVIDIA_AICITY/HEAD/result1.npy -------------------------------------------------------------------------------- /result2.npy: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevaldoshi17/NVIDIA_AICITY/HEAD/result2.npy -------------------------------------------------------------------------------- /Images/pipeline1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevaldoshi17/NVIDIA_AICITY/HEAD/Images/pipeline1.png -------------------------------------------------------------------------------- /Images/pipeline2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevaldoshi17/NVIDIA_AICITY/HEAD/Images/pipeline2.png -------------------------------------------------------------------------------- /Images/pipeline3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevaldoshi17/NVIDIA_AICITY/HEAD/Images/pipeline3.png -------------------------------------------------------------------------------- /Result.txt: -------------------------------------------------------------------------------- 1 | 1 59 1 2 | 6 49 1 3 | 12 174 1 4 | 17 100 1 5 | 32 757 1 6 | 35 307 1 7 | 37 693 1 8 | 38 99 1 9 | 46 124 1 10 | 48 138 1 11 | 51 86 1 12 | 55 60 1 13 | 68 269 1 14 | 85 243 1 15 | 11 293 1 16 | 24 184 1 17 | 71 40 1 18 | 96 163 1 19 | -------------------------------------------------------------------------------- /Masks/Readme.md: -------------------------------------------------------------------------------- 1 | -- Segmentation Maps 2 | 1. Run `python3 extract_frames.py` to extract frames from the videos with frequency set as 10. 3 | 2. Run pretrained Yolo v3 model on the original_images folder and save it as `part1.json`. To reduce complexity, we divided the task into two parts and saved it as part1.json and part2.json. 4 | 3. Run `Seg_masks.py`. 5 | 4. Run `python3 Masks/get_ignore_area.py`. 6 | 5. Computed Segmentation Masks can be downloaded from [here](https://drive.google.com/file/d/15mcjQx02CQ4sgJ9k4UG718wwPpoGAlS4/view?usp=sharing). 7 | -------------------------------------------------------------------------------- /extract_processed.py: -------------------------------------------------------------------------------- 1 | import os 2 | import cv2 3 | from natsort import natsorted 4 | 5 | base = "processed_images/" 6 | base2 = "processed_images2/" 7 | 8 | folders = natsorted(os.listdir(base)) 9 | 10 | for fo in folders: 11 | files = natsorted(os.listdir(base+fo+'/')) 12 | if not os.path.isdir(base2+fo): 13 | os.mkdir(base2+fo) 14 | 15 | for f in files: 16 | D = cv2.imread(base+fo+'/'+f) 17 | cv2.imwrite(base2+fo+ "/" +f.split('.')[0] + "_1" + ".jpg",D[:,0:400,:]) 18 | cv2.imwrite(base2+fo+ "/" +f.split('.')[0] + "_2" + ".jpg",D[:,200:600,:]) 19 | cv2.imwrite(base2+fo+ "/" +f.split('.')[0] + "_3" + ".jpg",D[:,400:800,:]) 20 | 21 | -------------------------------------------------------------------------------- /Masks/get_ignore_area.py: -------------------------------------------------------------------------------- 1 | from skimage.measure import label 2 | from scipy.ndimage.filters import gaussian_filter 3 | import cv2 4 | import numpy as np 5 | import matplotlib.pyplot as plt 6 | video_ids = np.arange(1,101) 7 | # video_ids = [1] 8 | count_thred = 0.02 9 | min_area = 500 10 | gass_sigma = 2 11 | score_thred = 0.1 12 | 13 | for video_id in video_ids: 14 | dt_results_fbf = {} 15 | with open("%s.txt"%(video_id),'r') as f: 16 | for line in f: 17 | line = line.rstrip() 18 | word = line.split(',') 19 | frame = int(word[0]) 20 | x1 = int(float(word[2])) 21 | y1 = int(float(word[3])) 22 | tmp_w = int(float(word[4])) 23 | tmp_h = int(float(word[5])) 24 | score = float(word[6]) 25 | if frame not in dt_results_fbf: 26 | dt_results_fbf[frame]=[] 27 | if score > score_thred : 28 | dt_results_fbf[frame].append([x1,y1,x1+tmp_w,y1+tmp_h,score]) 29 | 30 | # im = cv2.imread("data/AIC_Track3/ori_images/%s/1.jpg"%video_id) 31 | 32 | h = 410 33 | w = 800 34 | c = 3 35 | mat = np.zeros((h,w)) 36 | # print(len(dt_results_fbf)) 37 | for frame in dt_results_fbf: 38 | if frame <18000: 39 | tmp_score = np.zeros((h,w)) 40 | 41 | for box in dt_results_fbf[frame]: 42 | score = box[4] 43 | tmp_score[int(float(box[1])):int(float(box[3])),int(float(box[0])):int(float(box[2]))] = np.maximum(score,tmp_score[int(float(box[1])):int(float(box[3])),int(float(box[0])):int(float(box[2]))]) 44 | 45 | mat = mat+tmp_score 46 | # plt.imshow(mat) 47 | # plt.show() 48 | mat = mat-np.min(mat) 49 | mat = mat/np.max(mat) 50 | mask= mat>count_thred 51 | mask = label(mask, connectivity = 1) 52 | num = np.max(mask) 53 | print(num) 54 | for i in range(1,int(num+1)): 55 | if np.sum(mask==i)0 58 | mask = mask.astype(float) 59 | k = gaussian_filter(mask,gass_sigma) 60 | mask = k>count_thred 61 | np.save("Mas/%s.npy"%str(video_id),mask) 62 | -------------------------------------------------------------------------------- /extract_frames.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import os 3 | import glob 4 | import tqdm 5 | from pathlib import Path 6 | import numpy as np 7 | 8 | root = "../Data/test-data/" 9 | dest_dir = "ori_images/" 10 | video_names = [str(i)+'.mp4' for i in range(1,101)] 11 | print("capture videos") 12 | for video_name in tqdm.tqdm(video_names): 13 | file_name = video_name 14 | folder_name = dest_dir+file_name.split('.')[0] 15 | os.makedirs(folder_name,exist_ok=True) 16 | vc = cv2.VideoCapture(root+video_name) 17 | c = 1 18 | if vc.isOpened(): 19 | rval, frame = vc.read() 20 | else: 21 | rval = False 22 | 23 | timeF =100 24 | pic_path = folder_name+'/' 25 | 26 | while rval: 27 | if (c % timeF == 0): 28 | cv2.imwrite(pic_path + str(c) + '.jpg', frame) 29 | c = c + 1 30 | cv2.waitKey(1) 31 | rval, frame = vc.read() 32 | vc.release() 33 | 34 | dest_dir_processed = "processed_images/" 35 | 36 | if not os.path.isdir(dest_dir_processed): 37 | os.mkdir(dest_dir_processed) 38 | print("average images") 39 | for i in tqdm.tqdm(range(1,101)): 40 | video_name = str(i) 41 | path_file_number=glob.glob(os.path.join(dest_dir,video_name,'*.jpg')) 42 | internal_frame = 4 43 | start_frame = 100 44 | video_name = str(i) 45 | nums_frames = len(path_file_number) 46 | alpha=0.1 47 | Path(dest_dir_processed+video_name).mkdir(exist_ok=True) 48 | 49 | for j in range(4,5): 50 | internal_frame = 100 51 | num_pic = int(nums_frames) 52 | former_im = cv2.imread(dest_dir+"%d/100.jpg"%i) 53 | img = cv2.imread(os.path.join(dest_dir,video_name,str(start_frame)+'.jpg')) 54 | for i in range(num_pic): 55 | # print(os.path.join(dest_dir,video_name,str(start_frame)+'.jpg')) 56 | # print(os.path.join(dest_dir,video_name,str(i*internal_frame+start_frame)+'.jpg')) 57 | now_im = cv2.imread(os.path.join(dest_dir,video_name,str(i*internal_frame+start_frame)+'.jpg')) 58 | if np.mean(np.abs(now_im-former_im))>5: 59 | img = img*(1-alpha)+now_im*alpha 60 | cv2.imwrite(dest_dir_processed+video_name+'/'+str(i*internal_frame+start_frame) 61 | +'_'+str(j)+'.jpg',img) 62 | else: 63 | cv2.imwrite(dest_dir_processed+video_name+'/'+str(i*internal_frame+start_frame) 64 | +'_'+str(j)+'.jpg',img*0) 65 | former_im = now_im 66 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # NVIDIA AICITY CHALLENGE 2020 2 | 3 | 🏆 Our team got the second position at the AI CITY 2020 Challenge Track 4. 4 | 5 | ## Fast Unsupervised Anomaly Detection for Traffic Videos 6 | 7 | This repository contains our source code of Track 4 in the NVIDIA AI City Challenge at CVPR 2020. 8 | 9 | ### Introduction 10 | 11 | #### NVIDIA AICity Challenge 2020 Track 4 12 | 13 | The Track 4 of NVIDIA AI CITY 2020 comprised of detecting anomalies based on different video feeds available from multiple cameras at intersections and along highways. 14 | 15 | Detailed information of NVIDIA AICity Challenge 2020 can be found [here](https://www.aicitychallenge.org/). 16 | 17 | 18 | Overview of the architecture of our anomaly detection framework, which consists of three main pipelines. 19 | 20 | ### Requirements 21 | 22 | 1. Python 3.6 23 | 2. To run the model from scratch, please request data from the organizers. 24 | 3. Install Yolo-v3 from [here](https://github.com/AlexeyAB/darknet) and use pretrained model on MS-COCO. 25 | 26 | To run model from scratch, please follow these steps: 27 | 28 | ### Pipeline 1 29 |

30 | 31 |

32 | 33 | -- Background Modelling 34 | 1. Run `python extract_frames.py` to extract frames from the videos with frequency set as 100. 35 | 2. Run `python extract_processed.py` to segment the processed images. 36 | 3. Run pretrained Yolo v3 model on the processed_images2 folder and save it as `result.json`. 37 | 38 | -- Segmentation Maps 39 | 1. Run `python3 extract_frames.py` to extract frames from the videos with frequency set as 10. 40 | 2. Run pretrained Yolo v3 model on the original_images folder and save it as `part1.json`. To reduce complexity, we divided the task into two parts and saved it as part1.json and part2.json. 41 | 3. Run `Seg_masks.py`. 42 | 4. Run `python3 Masks/get_ignore_area.py`. 43 | 5. Computed Segmentation Masks can be downloaded from [here](https://drive.google.com/file/d/15mcjQx02CQ4sgJ9k4UG718wwPpoGAlS4/view?usp=sharing). 44 | 45 | ### Pipeline 2 46 |

47 | 48 |

49 | 50 | 51 | 1. Run `python3 Detector.py` and the results will be saved in `Results.txt`. 52 | 53 | ### Pipeline 3 54 |

55 | 56 |

57 | 58 | Since it would take a considerable amount of time to run all the steps from scratch, we have also provided precalculated results. You can directly see the result by running 'python3 Detector.py' or see it on the Jupyter notebook `Detector.ipynb`. 59 | 60 | 61 | ### Citation 62 | 63 | ``` 64 | @inproceedings{doshi2020fast, 65 | title={Fast Unsupervised Anomaly Detection in Traffic Videos}, 66 | author={Doshi, Keval and Yilmaz, Yasin}, 67 | booktitle={Proc. CVPR Workshops, Seattle, WA, USA}, 68 | year={2020} 69 | } 70 | 71 | ``` 72 | -------------------------------------------------------------------------------- /Seg_masks.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # coding: utf-8 3 | 4 | # In[1]: 5 | 6 | 7 | import numpy as np 8 | import json 9 | 10 | 11 | # In[5]: 12 | 13 | 14 | with open('Masks/part2.json', 'r') as f: 15 | D = json.load(f) 16 | 17 | 18 | # In[ ]: 19 | 20 | 21 | Folder = set(np.arange(1,101))-set(np.array([ 1, 4, 6, 9, 11, 15, 16, 17, 22, 24, 27, 28, 29, 30, 34, 35, 37,38, 40, 41, 42, 44, 46, 52, 54, 57, 63, 68, 71, 75, 76, 79, 80, 81,82, 84, 89, 96])) 22 | Folder = list(Folder) 23 | 24 | 25 | # In[115]: 26 | 27 | 28 | i = 0 29 | names = ["car","bus","truck"] 30 | 31 | for frame in D: 32 | # print(frame['filename'],frame['filename'].split('/')[4]) 33 | if frame['filename'].split('/')[4] == str(Folder[i]): 34 | 35 | file1 = open("Masks/" +str(Folder[i]) + ".txt","a") 36 | # print(frame['filename']) 37 | for bound in frame['objects']: 38 | if bound['name'] in names: 39 | frame_n = frame['filename'].split('/')[5].split('.')[0] 40 | # print(frame_n) 41 | a = -1 42 | b = bound['relative_coordinates']['center_x']*800 43 | c = bound['relative_coordinates']['center_y']*410 44 | d = bound['relative_coordinates']['width']*800 45 | e = bound['relative_coordinates']['height']*410 46 | f = bound['confidence'] 47 | g = -1 48 | h = -1 49 | j = -1 50 | line = [frame_n,a,b,c,d,e,f,g,h,j] 51 | for l in line: 52 | file1.write(str(l)+",") 53 | file1.write("\n") 54 | file1.close() 55 | 56 | 57 | 58 | 59 | # In[6]: 60 | 61 | 62 | with open('Masks/part1.json', 'r') as f: 63 | D = json.load(f) 64 | 65 | 66 | # In[7]: 67 | 68 | 69 | np.array([ 1, 4, 6, 9, 11, 15, 16, 17, 22, 24, 27, 28, 29, 30, 34, 35, 37,38, 40, 41, 42, 44, 46, 52, 54, 57, 63, 68, 71, 75, 76, 79, 80, 81,82, 84, 89, 96]) 70 | 71 | 72 | # In[ ]: 73 | 74 | 75 | i = 0 76 | names = ["car","bus","truck"] 77 | 78 | for frame in D: 79 | # print(frame['filename'],frame['filename'].split('/')[4]) 80 | if frame['filename'].split('/')[4] == str(Folder[i]): 81 | 82 | file1 = open("Masks/" +str(Folder[i]) + ".txt","a") 83 | # print(frame['filename']) 84 | for bound in frame['objects']: 85 | if bound['name'] in names: 86 | frame_n = frame['filename'].split('/')[5].split('.')[0] 87 | # print(frame_n) 88 | a = -1 89 | b = bound['relative_coordinates']['center_x']*800 90 | c = bound['relative_coordinates']['center_y']*410 91 | d = bound['relative_coordinates']['width']*800 92 | e = bound['relative_coordinates']['height']*410 93 | f = bound['confidence'] 94 | g = -1 95 | h = -1 96 | j = -1 97 | line = [frame_n,a,b,c,d,e,f,g,h,j] 98 | for l in line: 99 | file1.write(str(l)+",") 100 | file1.write("\n") 101 | file1.close() 102 | 103 | 104 | -------------------------------------------------------------------------------- /Detector.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # coding: utf-8 3 | 4 | # In[1]: 5 | 6 | 7 | from collections import Counter, defaultdict 8 | from kneed import KneeLocator 9 | from sklearn.cluster import KMeans 10 | from matplotlib.patches import Rectangle 11 | from vid_utils import * 12 | 13 | import numpy as np 14 | import cv2 15 | import numpy as np 16 | import pandas as pd 17 | import matplotlib.pyplot as plt 18 | import json 19 | from os import path 20 | 21 | 22 | # In[2]: 23 | 24 | 25 | with open('result.json', 'r') as f: 26 | D = json.load(f) 27 | 28 | 29 | # ## Extract Objects 30 | 31 | # In[3]: 32 | 33 | 34 | All_Cords = extract_objects(D) 35 | 36 | 37 | # ## Extract Cases 38 | 39 | # In[4]: 40 | 41 | 42 | AT = extract_cases(All_Cords) 43 | 44 | 45 | # ## Detect Change in Camera 46 | 47 | # In[6]: 48 | 49 | 50 | Base = "processed_images/" 51 | if path.exists("change.npy"): 52 | change_cam,loc,Cstat = np.load("change.npy",allow_pickle=True) 53 | else: 54 | change_cam, loc,Cstat = change_detect(Base) 55 | np.save("change.npy",[change_cam,loc,Cstat]) 56 | 57 | 58 | # In[7]: 59 | 60 | 61 | PT = list(set(AT) - set(change_cam)) 62 | 63 | 64 | # ## Case 1: Extract ROI 65 | 66 | # In[8]: 67 | 68 | 69 | if path.exists("centers1.npy"): 70 | Centers = np.load("centers1.npy",allow_pickle=True) 71 | else: 72 | Centers = extract_roi(PT,All_Cords) 73 | np.save("centers1.npy",Centers) 74 | 75 | 76 | # In[9]: 77 | 78 | 79 | len(Centers) 80 | 81 | 82 | # ## Case 1: Extract Bounds 83 | 84 | # In[10]: 85 | 86 | 87 | 88 | 89 | if path.exists("bounds1.npy"): 90 | Bounds = np.load("bounds1.npy",allow_pickle=True) 91 | else: 92 | Bounds = extract_bounds(Centers,PT,All_Cords) 93 | np.save("bounds1.npy",Bounds) 94 | 95 | 96 | # In[11]: 97 | 98 | 99 | len(Bounds) 100 | 101 | 102 | # ## Case 1: Backtracking 103 | 104 | # In[12]: 105 | 106 | 107 | Base = "ori_images/" 108 | 109 | if path.exists("result1.npy"): 110 | Times, Stat = np.load("result1.npy",allow_pickle=True) 111 | else: 112 | Times, Stat = backtrack(Bounds,PT,Base) 113 | np.save("result1.npy",[Times,Stat]) 114 | 115 | 116 | # ## Case 2: Extract ROI 117 | 118 | # In[13]: 119 | 120 | 121 | if path.exists("centers2.npy"): 122 | Centers2 = np.load("centers2.npy",allow_pickle=True) 123 | else: 124 | Centers2 = extract_roi1(change_cam,All_Cords,loc) 125 | np.save("centers2.npy",Centers2) 126 | 127 | 128 | # ## Case 2: Extract Bounds 129 | 130 | # In[14]: 131 | 132 | 133 | if path.exists("bounds2.npy"): 134 | Bounds2 = np.load("bounds2.npy",allow_pickle=True) 135 | else: 136 | Bounds2 = extract_bounds1(Centers2,change_cam,loc,All_Cords) 137 | np.save("bounds2.npy",Bounds2) 138 | 139 | 140 | # ## Case 2: Backtracking 141 | 142 | # In[15]: 143 | 144 | 145 | len(Centers),len(Centers2) 146 | 147 | 148 | # In[16]: 149 | 150 | 151 | len(Bounds),len(Bounds2) 152 | 153 | 154 | # In[17]: 155 | 156 | 157 | Base = "ori_images/" 158 | 159 | 160 | if path.exists("result2.npy"): 161 | Times2, Stat2 = np.load("result2.npy",allow_pickle=True) 162 | else: 163 | Times2, Stat2 = backtrack1(Bounds2,Base) 164 | np.save("result2.npy",[Times2,Stat2]) 165 | 166 | 167 | # In[18]: 168 | 169 | 170 | Times = {key:val for key, val in Times.items() if val != 999} 171 | Times = {key:val for key, val in Times.items() if val >= 40} 172 | 173 | Times2 = {key:val for key, val in Times2.items() if val != 999} 174 | Times2 = {key:val for key, val in Times2.items() if val >= 40} 175 | 176 | 177 | # In[23]: 178 | 179 | 180 | file1 = open("Result" + ".txt","w") 181 | for x in Times: 182 | file1.write('{0:2d} {1:3d} {2:1d}'.format(x,int(Times[x]),1)) 183 | file1.write("\n") 184 | 185 | for x in Times2: 186 | file1.write('{0:2d} {1:3d} {2:1d}'.format(x,int(Times2[x]),1)) 187 | file1.write("\n") 188 | 189 | file1.close() 190 | 191 | 192 | # In[ ]: 193 | 194 | 195 | 196 | 197 | -------------------------------------------------------------------------------- /Seg_masks.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "import cv2\n", 10 | "import numpy as np\n", 11 | "import pandas as pd\n", 12 | "import matplotlib.pyplot as plt\n", 13 | "import json\n" 14 | ] 15 | }, 16 | { 17 | "cell_type": "code", 18 | "execution_count": 5, 19 | "metadata": {}, 20 | "outputs": [], 21 | "source": [ 22 | "with open('Masks/part2.json', 'r') as f:\n", 23 | " D = json.load(f)" 24 | ] 25 | }, 26 | { 27 | "cell_type": "code", 28 | "execution_count": null, 29 | "metadata": {}, 30 | "outputs": [], 31 | "source": [ 32 | "Folder = set(np.arange(1,101))-set(np.array([ 1, 4, 6, 9, 11, 15, 16, 17, 22, 24, 27, 28, 29, 30, 34, 35, 37,38, 40, 41, 42, 44, 46, 52, 54, 57, 63, 68, 71, 75, 76, 79, 80, 81,82, 84, 89, 96]))\n", 33 | "Folder = list(Folder)\n" 34 | ] 35 | }, 36 | { 37 | "cell_type": "code", 38 | "execution_count": 115, 39 | "metadata": {}, 40 | "outputs": [], 41 | "source": [ 42 | "i = 0\n", 43 | "names = [\"car\",\"bus\",\"truck\"]\n", 44 | "\n", 45 | "for frame in D:\n", 46 | "# print(frame['filename'],frame['filename'].split('/')[4])\n", 47 | " if frame['filename'].split('/')[4] == str(Folder[i]):\n", 48 | "\n", 49 | " file1 = open(\"Masks/\" +str(Folder[i]) + \".txt\",\"a\")\n", 50 | "# print(frame['filename'])\n", 51 | " for bound in frame['objects']:\n", 52 | " if bound['name'] in names:\n", 53 | " frame_n = frame['filename'].split('/')[5].split('.')[0]\n", 54 | "# print(frame_n)\n", 55 | " a = -1\n", 56 | " b = bound['relative_coordinates']['center_x']*800\n", 57 | " c = bound['relative_coordinates']['center_y']*410\n", 58 | " d = bound['relative_coordinates']['width']*800\n", 59 | " e = bound['relative_coordinates']['height']*410\n", 60 | " f = bound['confidence']\n", 61 | " g = -1\n", 62 | " h = -1\n", 63 | " j = -1\n", 64 | " line = [frame_n,a,b,c,d,e,f,g,h,j]\n", 65 | " for l in line:\n", 66 | " file1.write(str(l)+\",\")\n", 67 | " file1.write(\"\\n\")\n", 68 | " file1.close()\n", 69 | " \n", 70 | " " 71 | ] 72 | }, 73 | { 74 | "cell_type": "code", 75 | "execution_count": 6, 76 | "metadata": {}, 77 | "outputs": [], 78 | "source": [ 79 | "with open('Masks/part1.json', 'r') as f:\n", 80 | " D = json.load(f)" 81 | ] 82 | }, 83 | { 84 | "cell_type": "code", 85 | "execution_count": 7, 86 | "metadata": {}, 87 | "outputs": [ 88 | { 89 | "data": { 90 | "text/plain": [ 91 | "array([ 1, 4, 6, 9, 11, 15, 16, 17, 22, 24, 27, 28, 29, 30, 34, 35, 37,\n", 92 | " 38, 40, 41, 42, 44, 46, 52, 54, 57, 63, 68, 71, 75, 76, 79, 80, 81,\n", 93 | " 82, 84, 89, 96])" 94 | ] 95 | }, 96 | "execution_count": 7, 97 | "metadata": {}, 98 | "output_type": "execute_result" 99 | } 100 | ], 101 | "source": [ 102 | "np.array([ 1, 4, 6, 9, 11, 15, 16, 17, 22, 24, 27, 28, 29, 30, 34, 35, 37,38, 40, 41, 42, 44, 46, 52, 54, 57, 63, 68, 71, 75, 76, 79, 80, 81,82, 84, 89, 96])" 103 | ] 104 | }, 105 | { 106 | "cell_type": "code", 107 | "execution_count": null, 108 | "metadata": {}, 109 | "outputs": [], 110 | "source": [ 111 | "i = 0\n", 112 | "names = [\"car\",\"bus\",\"truck\"]\n", 113 | "\n", 114 | "for frame in D:\n", 115 | "# print(frame['filename'],frame['filename'].split('/')[4])\n", 116 | " if frame['filename'].split('/')[4] == str(Folder[i]):\n", 117 | "\n", 118 | " file1 = open(\"Masks/\" +str(Folder[i]) + \".txt\",\"a\")\n", 119 | "# print(frame['filename'])\n", 120 | " for bound in frame['objects']:\n", 121 | " if bound['name'] in names:\n", 122 | " frame_n = frame['filename'].split('/')[5].split('.')[0]\n", 123 | "# print(frame_n)\n", 124 | " a = -1\n", 125 | " b = bound['relative_coordinates']['center_x']*800\n", 126 | " c = bound['relative_coordinates']['center_y']*410\n", 127 | " d = bound['relative_coordinates']['width']*800\n", 128 | " e = bound['relative_coordinates']['height']*410\n", 129 | " f = bound['confidence']\n", 130 | " g = -1\n", 131 | " h = -1\n", 132 | " j = -1\n", 133 | " line = [frame_n,a,b,c,d,e,f,g,h,j]\n", 134 | " for l in line:\n", 135 | " file1.write(str(l)+\",\")\n", 136 | " file1.write(\"\\n\")\n", 137 | " file1.close()\n", 138 | " " 139 | ] 140 | } 141 | ], 142 | "metadata": { 143 | "kernelspec": { 144 | "display_name": "Python 3", 145 | "language": "python", 146 | "name": "python3" 147 | }, 148 | "language_info": { 149 | "codemirror_mode": { 150 | "name": "ipython", 151 | "version": 3 152 | }, 153 | "file_extension": ".py", 154 | "mimetype": "text/x-python", 155 | "name": "python", 156 | "nbconvert_exporter": "python", 157 | "pygments_lexer": "ipython3", 158 | "version": "3.7.4" 159 | } 160 | }, 161 | "nbformat": 4, 162 | "nbformat_minor": 2 163 | } 164 | -------------------------------------------------------------------------------- /Detector.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "from vid_utils import *\n", 10 | "\n", 11 | "import numpy as np\n", 12 | "import json\n", 13 | "from os import path" 14 | ] 15 | }, 16 | { 17 | "cell_type": "code", 18 | "execution_count": 2, 19 | "metadata": {}, 20 | "outputs": [], 21 | "source": [ 22 | "with open('result.json', 'r') as f:\n", 23 | " D = json.load(f)" 24 | ] 25 | }, 26 | { 27 | "cell_type": "markdown", 28 | "metadata": {}, 29 | "source": [ 30 | " ## Extract Objects" 31 | ] 32 | }, 33 | { 34 | "cell_type": "code", 35 | "execution_count": 3, 36 | "metadata": {}, 37 | "outputs": [], 38 | "source": [ 39 | "All_Cords = extract_objects(D)" 40 | ] 41 | }, 42 | { 43 | "cell_type": "markdown", 44 | "metadata": {}, 45 | "source": [ 46 | "## Extract Cases" 47 | ] 48 | }, 49 | { 50 | "cell_type": "code", 51 | "execution_count": 4, 52 | "metadata": {}, 53 | "outputs": [], 54 | "source": [ 55 | "AT = extract_cases(All_Cords)" 56 | ] 57 | }, 58 | { 59 | "cell_type": "markdown", 60 | "metadata": {}, 61 | "source": [ 62 | "## Detect Change in Camera" 63 | ] 64 | }, 65 | { 66 | "cell_type": "code", 67 | "execution_count": 6, 68 | "metadata": {}, 69 | "outputs": [], 70 | "source": [ 71 | "Base = \"processed_images/\"\n", 72 | "if path.exists(\"change.npy\"):\n", 73 | " change_cam,loc,Cstat = np.load(\"change.npy\",allow_pickle=True)\n", 74 | "else:\n", 75 | " change_cam, loc,Cstat = change_detect(Base)\n", 76 | " np.save(\"change.npy\",[change_cam,loc,Cstat])" 77 | ] 78 | }, 79 | { 80 | "cell_type": "code", 81 | "execution_count": 7, 82 | "metadata": {}, 83 | "outputs": [], 84 | "source": [ 85 | "PT = list(set(AT) - set(change_cam))" 86 | ] 87 | }, 88 | { 89 | "cell_type": "markdown", 90 | "metadata": {}, 91 | "source": [ 92 | "## Case 1: Extract ROI" 93 | ] 94 | }, 95 | { 96 | "cell_type": "code", 97 | "execution_count": 8, 98 | "metadata": {}, 99 | "outputs": [], 100 | "source": [ 101 | "if path.exists(\"centers1.npy\"):\n", 102 | " Centers = np.load(\"centers1.npy\",allow_pickle=True)\n", 103 | "else:\n", 104 | " Centers = extract_roi(PT,All_Cords)\n", 105 | " np.save(\"centers1.npy\",Centers)" 106 | ] 107 | }, 108 | { 109 | "cell_type": "code", 110 | "execution_count": 9, 111 | "metadata": {}, 112 | "outputs": [ 113 | { 114 | "data": { 115 | "text/plain": [ 116 | "56" 117 | ] 118 | }, 119 | "execution_count": 9, 120 | "metadata": {}, 121 | "output_type": "execute_result" 122 | } 123 | ], 124 | "source": [ 125 | "len(Centers)" 126 | ] 127 | }, 128 | { 129 | "cell_type": "markdown", 130 | "metadata": {}, 131 | "source": [ 132 | "## Case 1: Extract Bounds" 133 | ] 134 | }, 135 | { 136 | "cell_type": "code", 137 | "execution_count": 10, 138 | "metadata": {}, 139 | "outputs": [], 140 | "source": [ 141 | "\n", 142 | "\n", 143 | "if path.exists(\"bounds1.npy\"):\n", 144 | " Bounds = np.load(\"bounds1.npy\",allow_pickle=True)\n", 145 | "else:\n", 146 | " Bounds = extract_bounds(Centers,PT,All_Cords)\n", 147 | " np.save(\"bounds1.npy\",Bounds)" 148 | ] 149 | }, 150 | { 151 | "cell_type": "code", 152 | "execution_count": 11, 153 | "metadata": {}, 154 | "outputs": [ 155 | { 156 | "data": { 157 | "text/plain": [ 158 | "95" 159 | ] 160 | }, 161 | "execution_count": 11, 162 | "metadata": {}, 163 | "output_type": "execute_result" 164 | } 165 | ], 166 | "source": [ 167 | "len(Bounds)" 168 | ] 169 | }, 170 | { 171 | "cell_type": "markdown", 172 | "metadata": {}, 173 | "source": [ 174 | "## Case 1: Backtracking" 175 | ] 176 | }, 177 | { 178 | "cell_type": "code", 179 | "execution_count": 12, 180 | "metadata": {}, 181 | "outputs": [], 182 | "source": [ 183 | "Base = \"ori_images/\"\n", 184 | "\n", 185 | "if path.exists(\"result1.npy\"):\n", 186 | " Times, Stat = np.load(\"result1.npy\",allow_pickle=True)\n", 187 | "else:\n", 188 | " Times, Stat = backtrack(Bounds,PT,Base)\n", 189 | " np.save(\"result1.npy\",[Times,Stat])" 190 | ] 191 | }, 192 | { 193 | "cell_type": "markdown", 194 | "metadata": {}, 195 | "source": [ 196 | "## Case 2: Extract ROI " 197 | ] 198 | }, 199 | { 200 | "cell_type": "code", 201 | "execution_count": 13, 202 | "metadata": {}, 203 | "outputs": [], 204 | "source": [ 205 | "if path.exists(\"centers2.npy\"):\n", 206 | " Centers2 = np.load(\"centers2.npy\",allow_pickle=True)\n", 207 | "else:\n", 208 | " Centers2 = extract_roi1(change_cam,All_Cords,loc)\n", 209 | " np.save(\"centers2.npy\",Centers2)" 210 | ] 211 | }, 212 | { 213 | "cell_type": "markdown", 214 | "metadata": {}, 215 | "source": [ 216 | "## Case 2: Extract Bounds" 217 | ] 218 | }, 219 | { 220 | "cell_type": "code", 221 | "execution_count": 14, 222 | "metadata": {}, 223 | "outputs": [], 224 | "source": [ 225 | "if path.exists(\"bounds2.npy\"):\n", 226 | " Bounds2 = np.load(\"bounds2.npy\",allow_pickle=True)\n", 227 | "else:\n", 228 | " Bounds2 = extract_bounds1(Centers2,change_cam,loc,All_Cords)\n", 229 | " np.save(\"bounds2.npy\",Bounds2)\n" 230 | ] 231 | }, 232 | { 233 | "cell_type": "markdown", 234 | "metadata": {}, 235 | "source": [ 236 | "## Case 2: Backtracking" 237 | ] 238 | }, 239 | { 240 | "cell_type": "code", 241 | "execution_count": 15, 242 | "metadata": {}, 243 | "outputs": [ 244 | { 245 | "data": { 246 | "text/plain": [ 247 | "(56, 12)" 248 | ] 249 | }, 250 | "execution_count": 15, 251 | "metadata": {}, 252 | "output_type": "execute_result" 253 | } 254 | ], 255 | "source": [ 256 | "len(Centers),len(Centers2)" 257 | ] 258 | }, 259 | { 260 | "cell_type": "code", 261 | "execution_count": 16, 262 | "metadata": {}, 263 | "outputs": [ 264 | { 265 | "data": { 266 | "text/plain": [ 267 | "(95, 18)" 268 | ] 269 | }, 270 | "execution_count": 16, 271 | "metadata": {}, 272 | "output_type": "execute_result" 273 | } 274 | ], 275 | "source": [ 276 | "len(Bounds),len(Bounds2)" 277 | ] 278 | }, 279 | { 280 | "cell_type": "code", 281 | "execution_count": 17, 282 | "metadata": {}, 283 | "outputs": [ 284 | { 285 | "name": "stdout", 286 | "output_type": "stream", 287 | "text": [ 288 | "0\n", 289 | "1\n", 290 | "2\n", 291 | "3\n", 292 | "4\n", 293 | "5\n", 294 | "6\n", 295 | "7\n", 296 | "8\n", 297 | "9\n", 298 | "10\n", 299 | "11\n", 300 | "12\n", 301 | "13\n", 302 | "14\n", 303 | "15\n", 304 | "16\n", 305 | "17\n" 306 | ] 307 | } 308 | ], 309 | "source": [ 310 | "Base = \"ori_images/\"\n", 311 | "\n", 312 | "\n", 313 | "if path.exists(\"result2.npy\"):\n", 314 | " Times2, Stat2 = np.load(\"result2.npy\",allow_pickle=True)\n", 315 | "else:\n", 316 | " Times2, Stat2 = backtrack1(Bounds2,Base)\n", 317 | " np.save(\"result2.npy\",[Times2,Stat2])" 318 | ] 319 | }, 320 | { 321 | "cell_type": "code", 322 | "execution_count": 18, 323 | "metadata": {}, 324 | "outputs": [], 325 | "source": [ 326 | "Times = {key:val for key, val in Times.items() if val != 999}\n", 327 | "Times = {key:val for key, val in Times.items() if val >= 40}\n", 328 | "\n", 329 | "Times2 = {key:val for key, val in Times2.items() if val != 999}\n", 330 | "Times2 = {key:val for key, val in Times2.items() if val >= 40}" 331 | ] 332 | }, 333 | { 334 | "cell_type": "code", 335 | "execution_count": 23, 336 | "metadata": {}, 337 | "outputs": [], 338 | "source": [ 339 | "file1 = open(\"Result\" + \".txt\",\"w\")\n", 340 | "for x in Times:\n", 341 | " file1.write('{0:2d} {1:3d} {2:1d}'.format(x,int(Times[x]),1))\n", 342 | " file1.write(\"\\n\")\n", 343 | " \n", 344 | "for x in Times2:\n", 345 | " file1.write('{0:2d} {1:3d} {2:1d}'.format(x,int(Times2[x]),1))\n", 346 | " file1.write(\"\\n\")\n", 347 | " \n", 348 | "file1.close()" 349 | ] 350 | }, 351 | { 352 | "cell_type": "code", 353 | "execution_count": null, 354 | "metadata": {}, 355 | "outputs": [], 356 | "source": [] 357 | } 358 | ], 359 | "metadata": { 360 | "kernelspec": { 361 | "display_name": "Python 3", 362 | "language": "python", 363 | "name": "python3" 364 | }, 365 | "language_info": { 366 | "codemirror_mode": { 367 | "name": "ipython", 368 | "version": 3 369 | }, 370 | "file_extension": ".py", 371 | "mimetype": "text/x-python", 372 | "name": "python", 373 | "nbconvert_exporter": "python", 374 | "pygments_lexer": "ipython3", 375 | "version": "3.7.4" 376 | } 377 | }, 378 | "nbformat": 4, 379 | "nbformat_minor": 2 380 | } 381 | -------------------------------------------------------------------------------- /vid_utils.py: -------------------------------------------------------------------------------- 1 | from collections import Counter 2 | from kneed import KneeLocator 3 | import numpy as np 4 | from sklearn.cluster import KMeans 5 | from natsort import natsorted 6 | import cv2 7 | import pandas as pd 8 | import os 9 | from skimage import metrics 10 | from scipy.signal import savgol_filter 11 | 12 | 13 | 14 | def Kmeans_clu(data,k): 15 | 16 | kmeans = KMeans(n_clusters=k, max_iter=10000, n_init=10).fit(data) ##Apply k-means clustering 17 | labels = kmeans.labels_ 18 | clu_centres = kmeans.cluster_centers_ 19 | z={i: np.where(kmeans.labels_ == i)[0] for i in range(kmeans.n_clusters)} 20 | 21 | return clu_centres, labels ,z,kmeans 22 | 23 | def reject_outliers(data): 24 | m = 2 25 | u = np.mean(data) 26 | s = np.std(data) 27 | filtered = [e for e in data if (u - 2 * s < e < u + 2 * s)] 28 | return np.array(filtered) 29 | 30 | 31 | def check_continual(stat,k): 32 | Found = False 33 | inx = (stat>0.5).astype(int) 34 | for ix in range(0,len(inx)-k,k): 35 | if np.min((inx[ix:ix+k])) == 1: 36 | Found = True 37 | return Found 38 | 39 | 40 | def nms(boxes, overlapThresh): 41 | # if there are no boxes, return an empty list 42 | if len(boxes) == 0: 43 | return [] 44 | 45 | # if the bounding boxes integers, convert them to floats -- 46 | # this is important since we'll be doing a bunch of divisions 47 | if boxes.dtype.kind == "i": 48 | boxes = boxes.astype("float") 49 | 50 | # initialize the list of picked indexes 51 | pick = [] 52 | 53 | # grab the coordinates of the bounding boxes 54 | x1 = boxes[:,0] - (boxes[:,3]/2) 55 | y1 = boxes[:,1] - (boxes[:,2]/2) 56 | x2 = boxes[:,0] + (boxes[:,3]/2) 57 | y2 = boxes[:,1] + (boxes[:,2]/2) 58 | 59 | # compute the area of the bounding boxes and sort the bounding 60 | # boxes by the bottom-right y-coordinate of the bounding box 61 | area = (x2 - x1 + 1) * (y2 - y1 + 1) 62 | idxs = np.argsort(y2) 63 | 64 | # keep looping while some indexes still remain in the indexes 65 | # list 66 | while len(idxs) > 0: 67 | # grab the last index in the indexes list and add the 68 | # index value to the list of picked indexes 69 | last = len(idxs) - 1 70 | i = idxs[last] 71 | pick.append(i) 72 | 73 | # find the largest (x, y) coordinates for the start of 74 | # the bounding box and the smallest (x, y) coordinates 75 | # for the end of the bounding box 76 | xx1 = np.maximum(x1[i], x1[idxs[:last]]) 77 | yy1 = np.maximum(y1[i], y1[idxs[:last]]) 78 | xx2 = np.minimum(x2[i], x2[idxs[:last]]) 79 | yy2 = np.minimum(y2[i], y2[idxs[:last]]) 80 | 81 | # compute the width and height of the bounding box 82 | w = np.maximum(0, xx2 - xx1 + 1) 83 | h = np.maximum(0, yy2 - yy1 + 1) 84 | 85 | # compute the ratio of overlap 86 | overlap = (w * h) / area[idxs[:last]] 87 | # print(overlap) 88 | 89 | # delete all indexes from the index list that have 90 | idxs = np.delete(idxs, np.concatenate(([last], 91 | np.where(overlap > overlapThresh)[0]))) 92 | 93 | # return only the bounding boxes that were picked using the 94 | # integer data type 95 | # print(pick) 96 | return boxes[pick] 97 | 98 | 99 | def extract_objects(D): 100 | 101 | c = 62 102 | valid_list = ['bus','truck','person','car','boat'] 103 | All_Cords = list() 104 | for vid in range(1,63): 105 | 106 | Vid_Cords = list() 107 | for file in range(22,266): 108 | Frame_Cords = list() 109 | 110 | if (len(D[c]['objects']))!=0: 111 | for bound in D[c]['objects']: 112 | if bound['name'] in valid_list: 113 | x = bound['relative_coordinates']['center_x']*400 114 | y = bound['relative_coordinates']['center_y']*410 115 | h = bound['relative_coordinates']['height']*410 116 | w = bound['relative_coordinates']['width']*400 117 | f = file 118 | if w*h > 16 and w>4 and h>4: 119 | Frame_Cords.append([x,y,h,w,f]) 120 | 121 | c+=1 122 | 123 | if (len(D[c]['objects']))!=0: 124 | for bound in D[c]['objects']: 125 | if bound['name'] in valid_list: 126 | x = bound['relative_coordinates']['center_x']*400 + 200 127 | y = bound['relative_coordinates']['center_y']*410 128 | h = bound['relative_coordinates']['height']*410 129 | w = bound['relative_coordinates']['width']*400 130 | f = file 131 | if w*h > 16 and w> 4 and h>4: 132 | Frame_Cords.append([x,y,h,w,f]) 133 | 134 | c+=1 135 | 136 | if (len(D[c]['objects']))!=0: 137 | for bound in D[c]['objects']: 138 | if bound['name'] in valid_list: 139 | x = bound['relative_coordinates']['center_x']*400 + 400 140 | y = bound['relative_coordinates']['center_y']*410 141 | h = bound['relative_coordinates']['height']*410 142 | w = bound['relative_coordinates']['width']*400 143 | f = file 144 | if w*h > 16 and w>4 and h>4: 145 | Frame_Cords.append([x,y,h,w,f]) 146 | 147 | c+=1 148 | 149 | Frame_Cords = nms(np.array(Frame_Cords),0.9) 150 | Vid_Cords.append(Frame_Cords) 151 | c+=67 152 | All_Cords.append(Vid_Cords) 153 | 154 | 155 | for vid in range(63,64): 156 | Vid_Cords = list() 157 | for file in range(22,232): 158 | Frame_Cords = list() 159 | 160 | if (len(D[c]['objects']))!=0: 161 | for bound in D[c]['objects']: 162 | if bound['name'] in valid_list: 163 | x = bound['relative_coordinates']['center_x']*400 164 | y = bound['relative_coordinates']['center_y']*410 165 | h = bound['relative_coordinates']['height']*410 166 | w = bound['relative_coordinates']['width']*400 167 | f = file 168 | if w*h > 16 and w> 4 and h>4: 169 | Frame_Cords.append([x,y,h,w,f]) 170 | 171 | c+=1 172 | 173 | if (len(D[c]['objects']))!=0: 174 | for bound in D[c]['objects']: 175 | if bound['name'] in valid_list: 176 | x = bound['relative_coordinates']['center_x']*400 + 200 177 | y = bound['relative_coordinates']['center_y']*410 178 | h = bound['relative_coordinates']['height']*410 179 | w = bound['relative_coordinates']['width']*400 180 | f = file 181 | if w*h > 16 and w>4 and h>4: 182 | Frame_Cords.append([x,y,h,w,f]) 183 | 184 | c+=1 185 | 186 | if (len(D[c]['objects']))!=0: 187 | for bound in D[c]['objects']: 188 | if bound['name'] in valid_list: 189 | x = bound['relative_coordinates']['center_x']*400 + 400 190 | y = bound['relative_coordinates']['center_y']*410 191 | h = bound['relative_coordinates']['height']*410 192 | w = bound['relative_coordinates']['width']*400 193 | f = file 194 | if w*h > 16 and w>4 and h>4: 195 | Frame_Cords.append([x,y,h,w,f]) 196 | 197 | c+=1 198 | 199 | Frame_Cords = nms(np.array(Frame_Cords),0.9) 200 | Vid_Cords.append(Frame_Cords) 201 | 202 | c+=67 203 | All_Cords.append(Vid_Cords) 204 | 205 | 206 | for vid in range(64,101): 207 | 208 | Vid_Cords = list() 209 | for file in range(22,266): 210 | Frame_Cords = list() 211 | 212 | if (len(D[c]['objects']))!=0: 213 | for bound in D[c]['objects']: 214 | if bound['name'] in valid_list: 215 | x = bound['relative_coordinates']['center_x']*400 216 | y = bound['relative_coordinates']['center_y']*410 217 | h = bound['relative_coordinates']['height']*410 218 | w = bound['relative_coordinates']['width']*400 219 | f = file 220 | if w*h > 16 and w>4 and h>4: 221 | Frame_Cords.append([x,y,h,w,f]) 222 | 223 | c+=1 224 | 225 | if (len(D[c]['objects']))!=0: 226 | for bound in D[c]['objects']: 227 | if bound['name'] in valid_list: 228 | x = bound['relative_coordinates']['center_x']*400 + 200 229 | y = bound['relative_coordinates']['center_y']*410 230 | h = bound['relative_coordinates']['height']*410 231 | w = bound['relative_coordinates']['width']*400 232 | f = file 233 | if w*h > 16 and w>4 and h>4: 234 | Frame_Cords.append([x,y,h,w,f]) 235 | 236 | c+=1 237 | 238 | if (len(D[c]['objects']))!=0: 239 | for bound in D[c]['objects']: 240 | if bound['name'] in valid_list: 241 | x = bound['relative_coordinates']['center_x']*400 + 400 242 | y = bound['relative_coordinates']['center_y']*410 243 | h = bound['relative_coordinates']['height']*410 244 | w = bound['relative_coordinates']['width']*400 245 | f = file 246 | if w*h > 16 and w>4 and h>4: 247 | Frame_Cords.append([x,y,h,w,f]) 248 | 249 | c+=1 250 | 251 | Frame_Cords = nms(np.array(Frame_Cords),0.9) 252 | Vid_Cords.append(Frame_Cords) 253 | 254 | c+=67 255 | All_Cords.append(Vid_Cords) 256 | 257 | return(All_Cords) 258 | 259 | 260 | 261 | def extract_cases(All_Cords): 262 | maxes = list() 263 | for i in range(0,100): 264 | 265 | T = np.array(All_Cords[i], dtype=object) 266 | AT = [item for sublist in T for item in sublist] 267 | AT = np.array(np.array(AT)).reshape(-1,5) 268 | 269 | new_idx = list() 270 | diss = list() 271 | if AT.shape[0] > 10: 272 | y = [] 273 | K = range(1,10) 274 | for k in K: 275 | km = KMeans(n_clusters=k,max_iter=10000, n_init=10) 276 | km = km.fit(AT[:,0:4]) 277 | y.append(km.inertia_) 278 | 279 | x = range(1, len(y)+1) 280 | 281 | 282 | kn = KneeLocator(x, y, curve='convex', direction='decreasing') 283 | k = (kn.knee) + 1 284 | 285 | if k == None: 286 | k = 10 287 | 288 | center,lb,z,kmeans = Kmeans_clu(AT[:,0:4],k) 289 | max_count = Counter(lb) 290 | 291 | if AT.shape[0] > 1: 292 | mx = max_count[max(max_count, key=max_count.get)] 293 | else: 294 | mx = 0 295 | else: 296 | mx = 0 297 | maxes.append(mx) 298 | 299 | PT = list(np.where(np.array(maxes) > 20)[0] + 1) 300 | return(PT) 301 | 302 | def extract_roi(PT,All_Cords): 303 | Centers = list() 304 | for i in PT: 305 | 306 | Mask = np.load("Masks/Mas/" + str(i)+ ".npy") 307 | T = np.array(All_Cords[i-1]) 308 | AT = [item for sublist in T for item in sublist] 309 | AT = np.array(np.array(AT)).reshape(-1,5) 310 | if AT.shape[0] > 20: 311 | y = [] 312 | K = range(1,10) 313 | for k in K: 314 | km = KMeans(n_clusters=k, max_iter=10000,n_init=10) 315 | km = km.fit(AT[:,0:4]) 316 | y.append(km.inertia_) 317 | 318 | x = range(1, len(y)+1) 319 | 320 | 321 | kn = KneeLocator(x, y, curve='convex', direction='decreasing') 322 | k = (kn.knee) + 1 323 | 324 | if k == None: 325 | k = 10 326 | 327 | center,lb,z,kmeans = Kmeans_clu(AT[:,0:4],k) 328 | vid_cent = list() 329 | for cent in center: 330 | y_m = np.max((0,int(cent[1])-10)) 331 | y_ma = np.min((410,int(cent[1])+10)) 332 | x_m = np.max((0,int(cent[0])-10)) 333 | x_ma = np.min((800,int(cent[0])+10)) 334 | if np.max(Mask[y_m:y_ma,x_m:x_ma]) == 1: 335 | vid_cent.append(cent) 336 | Centers.append(vid_cent) 337 | 338 | return(Centers) 339 | 340 | def extract_roi1(cam_change,All_Cords,loc): 341 | Centersf = list() 342 | for i in range(0,len(cam_change)): 343 | Centers = list() 344 | T = np.array(All_Cords[cam_change[i]-1]) 345 | AT = [item for sublist in T for item in sublist] 346 | AT = np.array(np.array(AT)).reshape(-1,5) 347 | imx = np.where(AT[:,4] >= 10*loc[i])[0][0] 348 | AT = AT[0:imx,:] 349 | 350 | Mask = np.load("Masks/Mas/" + str(cam_change[i])+ ".npy") 351 | 352 | if AT.shape[0] > 10: 353 | y = [] 354 | K = range(1,10) 355 | for k in K: 356 | km = KMeans(n_clusters=k, max_iter=10000,n_init=10) 357 | km = km.fit(AT[:,0:4]) 358 | y.append(km.inertia_) 359 | 360 | x = range(1, len(y)+1) 361 | kn = KneeLocator(x, y, curve='convex', direction='decreasing') 362 | k = (kn.knee) + 1 363 | 364 | if k == None: 365 | k = 10 366 | 367 | center,lb,z,kmeans = Kmeans_clu(AT[:,0:4],k) 368 | vid_cent = list() 369 | for cent in center: 370 | y_m = np.max((0,int(cent[1])-10)) 371 | y_ma = np.min((410,int(cent[1])+10)) 372 | x_m = np.max((0,int(cent[0])-10)) 373 | x_ma = np.min((800,int(cent[0])+10)) 374 | if np.max(Mask[y_m:y_ma,x_m:x_ma]) == 1: 375 | vid_cent.append(cent) 376 | 377 | Centers.append(vid_cent) 378 | Centersf.append(Centers) 379 | return Centersf 380 | 381 | def extract_bounds(Centers,PT,All_Cords): 382 | 383 | count = 0 384 | Bounds = list() 385 | for centro in Centers: 386 | 387 | T = np.array(All_Cords[-1+PT[count]]) 388 | AT = [item for sublist in T for item in sublist] 389 | AT = np.array(np.array(AT)).reshape(-1,5) 390 | 391 | count2 = 1 392 | for c in centro: 393 | Found = False 394 | idx = 0 395 | while not Found: 396 | if idx < len(AT): 397 | if np.abs(AT[idx,0] - c[0]) < 25 and np.abs(AT[idx,1] - c[1]) < 25 and AT[idx,2] < 100 and int(AT[idx,2]) >7 and int(AT[idx,3]) >7: 398 | 399 | Bounds.append([AT[idx,0:],PT[count],count2]) 400 | Found = True 401 | else: 402 | Found = True 403 | idx+=1 404 | count2+=1 405 | count+=1 406 | 407 | return(Bounds) 408 | 409 | 410 | def extract_bounds1(Centers,cam_change,loc,All_Cords): 411 | 412 | Bounds = list() 413 | for i in range(0,len(cam_change)): 414 | for centro in Centers[i]: 415 | 416 | T = np.array(All_Cords[cam_change[i]-1]) 417 | AT = [item for sublist in T for item in sublist] 418 | AT = np.array(np.array(AT)).reshape(-1,5) 419 | imx = np.where(AT[:,4] >= 10*loc[i])[0][0] 420 | AT = AT[0:imx,:] 421 | 422 | count2 = 1 423 | for c in centro: 424 | Found = False 425 | idx = 0 426 | while not Found: 427 | if idx < len(AT): 428 | if np.abs(AT[idx,0] - c[0]) < 25 and np.abs(AT[idx,1] - c[1]) < 25 and AT[idx,2] < 100 and int(AT[idx,2]) >6 and int(AT[idx,3]) >6: 429 | Bounds.append([AT[idx,0:],cam_change[i],count2]) 430 | Found = True 431 | else: 432 | Found = True 433 | idx+=1 434 | count2+=1 435 | 436 | return (Bounds) 437 | 438 | 439 | 440 | 441 | def change_detect(Base): 442 | 443 | All_stat3= list() 444 | Folders = natsorted(os.listdir(Base)) 445 | for i in range(len(Folders)): 446 | 447 | base2 = Base + str(Folders[i]) + "/" 448 | files = natsorted(os.listdir(base2)) 449 | stat = list() 450 | 451 | for idx in range(1,len(files)-10,10): 452 | 453 | img0 = cv2.imread(base2 + files[idx]) 454 | img1 = cv2.imread(base2 + files[idx+10]) 455 | sad = 0 456 | if np.sum(img1) != 0 and np.sum(img0) !=0: 457 | sad = metrics.structural_similarity(img0,img1,multichannel=True,win_size=3) 458 | else: 459 | sad = 0.99 460 | stat.append(np.max((0,sad))) 461 | All_stat3.append(stat) 462 | 463 | cam_change = list() 464 | loc = list() 465 | for ss in range(len(All_stat3)): 466 | # if len(np.where(np.array(All_stat3[ss]) < 0.87)[0]) > 0: 467 | if np.mean(All_stat3[ss]) - np.min((All_stat3[ss])) > 0.06: 468 | cam_change.append(ss+1) 469 | loc.append(-2+np.where(np.array(All_stat3[ss]) == np.min((All_stat3[ss])))[0][0]) 470 | 471 | return cam_change, loc, All_stat3 472 | 473 | def backtrack(Bounds, PT,Base): 474 | All_statfn= list() 475 | for i in range(0,len(Bounds)): 476 | if Bounds[i][1] in PT: 477 | base2 = Base + str(Bounds[i][1]) + "/" 478 | files = natsorted(os.listdir(base2)) 479 | stat = list() 480 | back_len = int(Bounds[i][0][4]*100) 481 | x = int(Bounds[i][0][0]) 482 | y = int(Bounds[i][0][1]) 483 | h = int(Bounds[i][0][2]/2) 484 | w = int(Bounds[i][0][3]/2) 485 | 486 | img0 = cv2.imread(base2 + str(back_len) +".jpg")[y-h:y+h,x-w:x+w] 487 | img0 = cv2.cvtColor(img0, cv2.COLOR_BGR2GRAY) 488 | 489 | for idx in range(np.min((26750,2*back_len)),90,-5): 490 | img1 = cv2.imread(base2 + str(idx) +".jpg")[y-h:y+h,x-w:x+w] 491 | img1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY) 492 | 493 | stat.append(metrics.structural_similarity(img0,img1,multichannel=True,win_size=3)) 494 | 495 | 496 | for idx in range(0,len(stat)-35): 497 | stat[idx] = np.max((stat[idx:idx+35])) 498 | 499 | All_statfn.append(stat) 500 | 501 | 502 | Times = {} 503 | count = 0 504 | for stat in All_statfn: 505 | Times[Bounds[count][1]] = 999 506 | count+=1 507 | 508 | count = 0 509 | for stat in All_statfn: 510 | 511 | if np.max((stat)) > 0.5 and np.min((stat))<0.65: 512 | stat = savgol_filter(stat,21,1) 513 | nstat = (list(reversed(stat)) -min(stat))/(max(stat)-min(stat)) 514 | Found = check_continual(nstat,150) 515 | if Found: 516 | Times[Bounds[count][1]] = np.min((Times[Bounds[count][1]],np.min(((np.where(np.array(nstat)>=0.4)[0][0])*5/30,Times[Bounds[count][1]])))) 517 | 518 | 519 | count+=1 520 | 521 | return Times, All_statfn 522 | 523 | 524 | def backtrack1(Bounds,Base): 525 | All_statfn= list() 526 | for i in range(0,len(Bounds)): 527 | print(i) 528 | base2 = Base + str(Bounds[i][1]) + "/" 529 | files = natsorted(os.listdir(base2)) 530 | stat = list() 531 | back_track = int(Bounds[i][0][4]*100) 532 | x = int(Bounds[i][0][0]) 533 | y = int(Bounds[i][0][1]) 534 | h = int(Bounds[i][0][2]/2) 535 | w = int(Bounds[i][0][3]/2) 536 | 537 | img0 = cv2.imread(base2 + str(back_track) +".jpg")[y-h:y+h,x-w:x+w] 538 | img0 = cv2.cvtColor(img0, cv2.COLOR_BGR2GRAY) 539 | 540 | for idx in range(np.min((26750,2*back_track)),90,-5): 541 | img1 = cv2.imread(base2 + str(idx) +".jpg")[y-h:y+h,x-w:x+w] 542 | img1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY) 543 | 544 | stat.append(metrics.structural_similarity(img0,img1,multichannel=True,win_size=3)) 545 | 546 | 547 | for idx in range(0,len(stat)-35): 548 | stat[idx] = np.max((stat[idx:idx+35])) 549 | 550 | 551 | All_statfn.append(stat) 552 | 553 | 554 | Times = {} 555 | count = 0 556 | for stat in All_statfn: 557 | Times[Bounds[count][1]] = 999 558 | 559 | count+=1 560 | 561 | count = 0 562 | for stat in All_statfn: 563 | stat = reject_outliers(stat) 564 | if np.max((stat)) > 0.5 and np.min((stat))<0.55: 565 | stat = savgol_filter(stat,21,1) 566 | 567 | nstat = (list(reversed(stat)) -min(stat))/(max(stat)-min(stat)) 568 | Found = check_continual(nstat,150) 569 | if Found: 570 | if (np.where(np.array(nstat)>=0.4))[0][0] != 0: 571 | Times[Bounds[count][1]] = np.min((Times[Bounds[count][1]],np.min(((np.where(np.array(nstat)>=0.5)[0][0])*5/30,Times[Bounds[count][1]])))) 572 | 573 | count+=1 574 | 575 | return Times,All_statfn 576 | 577 | 578 | 579 | 580 | 581 | 582 | 583 | 584 | 585 | --------------------------------------------------------------------------------