ich habe ein Problem, was schwierig zu lösen ist. Folgendes Programm wirft diesen Traceback:
File "d:\python_dev\GRAPHIC_ALARMING_MACHINE\SOURCECODE\GraphicAlarmMachine.py", line 302, in run
vid_cropped = vid[asset_data[roi_amount][4]: asset_data[roi_amount][4]+asset_data[roi_amount][6], asset_data[roi_amount][3]:asset_data[roi_amount][3]+asset_data[roi_amount][5]]
TypeError: 'NoneType' object is not subscriptable
Ich habe selbstverständlich den Pfad der Videodatei überprüft, der ist korrekt. Codecs usw. sind auch alle vorhanden und in Ordnung. Außerdem tritt dieser Fehler unregelmäßig auf. Ich habe die Vermutung, dass die dauerhafte Neubelegung mit dem cap = cv2.VideoCapture(get_latest_video) irgendwann zu einem internen overflow (?!) führt. Daher habe ich nach jedem iterationslauf ein cap.release() eingebaut. Wichtig ist noch, alles was hier zu sehen ist, ist ein Iterationsschritt mit jeweils unterschiedlichen Daten. Ich beoachte, dass der Traceback vorallem dann auftritt, wenn zwei Videos nacheinander analysiert werden. Wenn bei einem Video nix passiert und bei anderen etwas analysiert wird, tritt der Fehler weniger auf.
Da ich mir im Internet den Wolf gesucht habe und mein Problem dort nirgends in der Form auftritt, hoffe ich sehr, jemand kann mir helfen. Gerne erkläre ich das Programm, falls wichtige Dinge nicht aus dem Quellcode hervorgehen. Tausend Dank für jede Hilfestellung!
Code: Alles auswählen
if self.pts_list_global[index][row_var[(temp_name)]][3] <= timestamp:
if asset_data != False:
# sleep for checkintervall
sleep(asset_data[0][7])
# updating GUI
status = "analyzing"
self.statuslog.emit(status)
# calculate milliseonds for getting fps
samplecheck = 1/asset_data[0][8] *1000
samplecheck = int(samplecheck)
try:
# Load Video data
video_path_rebuild = self.init_videooperations.build_path(self.roi_channelconfig[index][1])
get_latest_video = self.init_videooperations.get_latest_vid(video_path_rebuild)
# ctime = modifydate. Therefor substract delaytime xentaurix
get_ctime_video = self.init_videooperations.video_ctime(get_latest_video, self.delaytime_xentaurix)
# substract xentaurix delay to get the right SOM
requested_event_in = self.pts_list_global[index][row_var[(temp_name)]][3] - dt.timedelta(minutes=int(self.delaytime_xentaurix[3:5]))
# Further progress: Add intervall length each time
start_frame_number = self.init_videooperations.calculate_som(get_ctime_video, requested_event_in)
# create cv2 videoobject
cap = cv2.VideoCapture(get_latest_video)
# Add delay for muxing. Different for SD/HD
delay_mux = self.roi_channelconfig[0][3] * 25
# Add muxing delay
start_frame_number_final = start_frame_number + delay_mux
# Add frames to calculate further frames in vid. Start 0 , += Intervall length
_som = som_progress[temp_name] * 25
start_frame_number_final_som = start_frame_number_final + _som
som_progress[temp_name] += asset_data[0][11]
# set correct start of the video
cap.set(cv2.CAP_PROP_POS_FRAMES, start_frame_number_final_som)
except Exception as e:
self.logger.error('Failed to load video data', exc_info=True)
try:
# Perform calulation for every asset (secondary under the same ID as Logo)
for roi_amount in range(len(asset_data)):
while True:
print(framecount[temp_name])
print(self.frames)
time_end = dt.datetime.now().replace(microsecond=0)
if self.frames == 0:
# Grap the time once fixed without changes over the loop
time_start = dt.datetime.now().replace(microsecond=0)
# read frame by frame
success, vid = cap.read()
# Wait for milliseconds to grap desired fps. formula (1/desired frames)*1000
cv2.waitKey(samplecheck)
# increase frames to prevent, that time_start will be changed
self.frames +=1
# eval framecount for later calculation in error_eval
framecount[temp_name] += 1
# in case if an secondary with the same Asset ID is given -> more then one ROI
vid_cropped = vid[asset_data[roi_amount][4]: asset_data[roi_amount][4]+asset_data[roi_amount][6], asset_data[roi_amount][3]:asset_data[roi_amount][3]+asset_data[roi_amount][5]]
# Convert Source to gray
gray = cv2.cvtColor(vid_cropped, cv2.COLOR_BGR2GRAY)
# Template for calculation
template = asset_data[roi_amount][10]
height, width = template.shape[::]
# cv2.TM_SQDIFF = Minimum Square Difference with Threshold
res = cv2.matchTemplate(gray, template, cv2.TM_CCOEFF_NORMED)
#For TM_CCOEFF_NORMED, larger values means good fit
threshold = asset_data[roi_amount][9]
# Return Tuple
loc = np.where( res >= threshold)
# Final result
if len(loc[0]) > 0:
self.resultlog.emit("True")
else:
errors_var[temp_name] += 1
self.resultlog.emit("false")
cap.release()
if time_end >= time_start + timedelta(seconds=asset_data[0][11]):
# write results in csv for later error evaluation
with open(r"D:\python_dev\GRAPHIC_ALARMING_MACHINE\ALARMING\alarms.csv", mode='a', newline="") as csv_file_writedata:
fieldnames = ['channelname', 'asset_id','framescount', 'false', 'timestamp', 'xentaurixdelay']
writer = csv.DictWriter(csv_file_writedata, fieldnames=fieldnames)
writer.writeheader()
writer.writerow({'channelname': temp_name , 'asset_id':asset_data[0][1], 'framescount': framecount[temp_name], 'false':errors_var[temp_name], 'timestamp':time_end, 'xentaurixdelay':self.roi_channelconfig[index][2]})
# reset for getting fixed time
self.frames = 0
# reset error variables
errors_var[temp_name] = 0
# reset framecount
framecount[temp_name] = 0
self.row_false = 0
cap.release()
# leave core calc loop
break
except Exception as e:
self.logger.error('Core Calculation failed for channel: '+temp_name, exc_info=True)
break