From f73805c62ab6a7a86631f3b2c1a7a624fb6e674e Mon Sep 17 00:00:00 2001 From: Richard Ellis Date: Thu, 7 Nov 2024 07:57:31 -0500 Subject: [PATCH 1/3] Avoid "TypeError: Argument 'value' must be double, not bool" in cap.set call. The change made both isPi and not isPi if branches identical, so remove the if clause entirely. --- src/tc001v4.2.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/tc001v4.2.py b/src/tc001v4.2.py index 8346f7d..667d6cd 100644 --- a/src/tc001v4.2.py +++ b/src/tc001v4.2.py @@ -55,10 +55,7 @@ def is_raspberrypi(): #cap = cv2.VideoCapture(0) #pull in the video but do NOT automatically convert to RGB, else it breaks the temperature data! #https://stackoverflow.com/questions/63108721/opencv-setting-videocap-property-to-cap-prop-convert-rgb-generates-weird-boolean -if isPi == True: - cap.set(cv2.CAP_PROP_CONVERT_RGB, 0.0) -else: - cap.set(cv2.CAP_PROP_CONVERT_RGB, False) +cap.set(cv2.CAP_PROP_CONVERT_RGB, 0.0) #256x192 General settings width = 256 #Sensor width From b0a177666cb6128c9ef8cff0b2d782435c8ae308 Mon Sep 17 00:00:00 2001 From: Richard Ellis Date: Thu, 7 Nov 2024 09:28:45 -0500 Subject: [PATCH 2/3] Add ability to display temperature in all three common units (Kelvin, Celsius, and Fahrenheit). Add menu key to rotate display through the three units. Add CLI option to choose a default temperature unit upon launch. --- src/tc001v4.2.py | 63 +++++++++++++++++++++++++++++++----------------- 1 file changed, 41 insertions(+), 22 deletions(-) diff --git a/src/tc001v4.2.py b/src/tc001v4.2.py index 667d6cd..0b76654 100644 --- a/src/tc001v4.2.py +++ b/src/tc001v4.2.py @@ -22,6 +22,7 @@ print('r t: Record and Stop') print('p : Snapshot') print('m : Cycle through ColorMaps') +print('u : Cycle through Temperature Units') print('h : Toggle HUD') import cv2 @@ -43,13 +44,22 @@ def is_raspberrypi(): parser = argparse.ArgumentParser() parser.add_argument("--device", type=int, default=0, help="Video Device number e.g. 0, use v4l2-ctl --list-devices") +parser.add_argument("--tempunits", default='C', help="Default temperature units to display ") args = parser.parse_args() if args.device: dev = args.device else: dev = 0 - + +if args.tempunits: + if args.tempunits in set(['K', 'k', 'C', 'c', 'F', 'f']): + temp_units = args.tempunits.upper() + else: + raise ValueError('Temperature units must be one of K, C or F') +else: + temp_units = "C" + #init video cap = cv2.VideoCapture('/dev/video'+str(dev), cv2.CAP_V4L) #cap = cv2.VideoCapture(0) @@ -88,7 +98,24 @@ def snapshot(heatmap): snaptime = time.strftime("%H:%M:%S") cv2.imwrite("TC001"+now+".png", heatmap) return snaptime - + +def convert_temp(temp): + global temp_units + if temp_units == "K": + return str(round(temp/64,2))+' K' + elif temp_units == "C": + return str(round(((temp/64)-273.15),2))+' C' + elif temp_units == "F": + return str(round(((temp/64)-273.15)*1.8+32,2))+' F' + +def change_temp_units(): + global temp_units + if temp_units == "K": + temp_units = 'C' + elif temp_units == "C": + temp_units = 'F' + elif temp_units == 'F': + temp_units = 'K' while(cap.isOpened()): # Capture frame-by-frame @@ -103,10 +130,7 @@ def snapshot(heatmap): lo = thdata[96][128][1] #print(hi,lo) lo = lo*256 - rawtemp = hi+lo - #print(rawtemp) - temp = (rawtemp/64)-273.15 - temp = round(temp,2) + temp = hi+lo #print(temp) #break @@ -118,8 +142,6 @@ def snapshot(heatmap): himax = thdata[mcol][mrow][0] lomax=lomax*256 maxtemp = himax+lomax - maxtemp = (maxtemp/64)-273.15 - maxtemp = round(maxtemp,2) #find the lowest temperature in the frame @@ -130,18 +152,12 @@ def snapshot(heatmap): himin = thdata[lcol][lrow][0] lomin=lomin*256 mintemp = himin+lomin - mintemp = (mintemp/64)-273.15 - mintemp = round(mintemp,2) #find the average temperature in the frame loavg = thdata[...,1].mean() hiavg = thdata[...,0].mean() loavg=loavg*256 avgtemp = loavg+hiavg - avgtemp = (avgtemp/64)-273.15 - avgtemp = round(avgtemp,2) - - # Convert the real image to RGB bgr = cv2.cvtColor(imdata, cv2.COLOR_YUV2BGR_YUYV) @@ -201,19 +217,19 @@ def snapshot(heatmap): cv2.line(heatmap,(int(newWidth/2)+20,int(newHeight/2)),\ (int(newWidth/2)-20,int(newHeight/2)),(0,0,0),1) #hline #show temp - cv2.putText(heatmap,str(temp)+' C', (int(newWidth/2)+10, int(newHeight/2)-10),\ + cv2.putText(heatmap,convert_temp(temp), (int(newWidth/2)+10, int(newHeight/2)-10),\ cv2.FONT_HERSHEY_SIMPLEX, 0.45,(0, 0, 0), 2, cv2.LINE_AA) - cv2.putText(heatmap,str(temp)+' C', (int(newWidth/2)+10, int(newHeight/2)-10),\ + cv2.putText(heatmap,convert_temp(temp), (int(newWidth/2)+10, int(newHeight/2)-10),\ cv2.FONT_HERSHEY_SIMPLEX, 0.45,(0, 255, 255), 1, cv2.LINE_AA) if hud==True: # display black box for our data cv2.rectangle(heatmap, (0, 0),(160, 120), (0,0,0), -1) # put text in the box - cv2.putText(heatmap,'Avg Temp: '+str(avgtemp)+' C', (10, 14),\ + cv2.putText(heatmap,'Avg Temp: '+convert_temp(avgtemp), (10, 14),\ cv2.FONT_HERSHEY_SIMPLEX, 0.4,(0, 255, 255), 1, cv2.LINE_AA) - cv2.putText(heatmap,'Label Threshold: '+str(threshold)+' C', (10, 28),\ + cv2.putText(heatmap,'Label Threshold: '+str(threshold), (10, 28),\ cv2.FONT_HERSHEY_SIMPLEX, 0.4,(0, 255, 255), 1, cv2.LINE_AA) cv2.putText(heatmap,'Colormap: '+cmapText, (10, 42),\ @@ -244,18 +260,18 @@ def snapshot(heatmap): if maxtemp > avgtemp+threshold: cv2.circle(heatmap, (mrow*scale, mcol*scale), 5, (0,0,0), 2) cv2.circle(heatmap, (mrow*scale, mcol*scale), 5, (0,0,255), -1) - cv2.putText(heatmap,str(maxtemp)+' C', ((mrow*scale)+10, (mcol*scale)+5),\ + cv2.putText(heatmap,convert_temp(maxtemp), ((mrow*scale)+10, (mcol*scale)+5),\ cv2.FONT_HERSHEY_SIMPLEX, 0.45,(0,0,0), 2, cv2.LINE_AA) - cv2.putText(heatmap,str(maxtemp)+' C', ((mrow*scale)+10, (mcol*scale)+5),\ + cv2.putText(heatmap,convert_temp(maxtemp), ((mrow*scale)+10, (mcol*scale)+5),\ cv2.FONT_HERSHEY_SIMPLEX, 0.45,(0, 255, 255), 1, cv2.LINE_AA) #display floating min temp if mintemp < avgtemp-threshold: cv2.circle(heatmap, (lrow*scale, lcol*scale), 5, (0,0,0), 2) cv2.circle(heatmap, (lrow*scale, lcol*scale), 5, (255,0,0), -1) - cv2.putText(heatmap,str(mintemp)+' C', ((lrow*scale)+10, (lcol*scale)+5),\ + cv2.putText(heatmap,convert_temp(mintemp), ((lrow*scale)+10, (lcol*scale)+5),\ cv2.FONT_HERSHEY_SIMPLEX, 0.45,(0,0,0), 2, cv2.LINE_AA) - cv2.putText(heatmap,str(mintemp)+' C', ((lrow*scale)+10, (lcol*scale)+5),\ + cv2.putText(heatmap,convert_temp(mintemp), ((lrow*scale)+10, (lcol*scale)+5),\ cv2.FONT_HERSHEY_SIMPLEX, 0.45,(0, 255, 255), 1, cv2.LINE_AA) #display image @@ -343,6 +359,9 @@ def snapshot(heatmap): if keyPress == ord('p'): #f to finish reording snaptime = snapshot(heatmap) + if keyPress == ord('u'): #u to toggle units for temperature display + change_temp_units() + if keyPress == ord('q'): break capture.release() From ab545d391efc4f6779d7f53c38d871f9586dbb5c Mon Sep 17 00:00:00 2001 From: Richard Ellis Date: Thu, 7 Nov 2024 10:31:18 -0500 Subject: [PATCH 3/3] Add image rotation (in 90 degree increments) including keyboard key to cycle and CLI option to choose a startup default. --- src/tc001v4.2.py | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/tc001v4.2.py b/src/tc001v4.2.py index 0b76654..02e7457 100644 --- a/src/tc001v4.2.py +++ b/src/tc001v4.2.py @@ -23,6 +23,7 @@ print('p : Snapshot') print('m : Cycle through ColorMaps') print('u : Cycle through Temperature Units') +print('o : Cycle through image rotation angles') print('h : Toggle HUD') import cv2 @@ -45,6 +46,7 @@ def is_raspberrypi(): parser = argparse.ArgumentParser() parser.add_argument("--device", type=int, default=0, help="Video Device number e.g. 0, use v4l2-ctl --list-devices") parser.add_argument("--tempunits", default='C', help="Default temperature units to display ") +parser.add_argument("--rotate", type=int, default=0, help="Default rotation angle <0|90|180|270>") args = parser.parse_args() if args.device: @@ -60,6 +62,22 @@ def is_raspberrypi(): else: temp_units = "C" +if args.rotate: + if args.rotate in set([0, 90, 180, 270]): + rotate = args.rotate + if rotate == 0: + rotate = None + elif rotate == 90: + rotate = cv2.ROTATE_90_CLOCKWISE + elif rotate == 180: + rotate = cv2.ROTATE_180 + elif rotate == 270: + rotate = cv2.ROTATE_90_COUNTERCLOCKWISE + else: + raise ValueError('Rotation value must be one of 0, 90, 180, 270.') +else: + rotate = None + #init video cap = cv2.VideoCapture('/dev/video'+str(dev), cv2.CAP_V4L) #cap = cv2.VideoCapture(0) @@ -117,6 +135,17 @@ def change_temp_units(): elif temp_units == 'F': temp_units = 'K' +def change_rotation(): + global rotate + if rotate is None: + rotate = cv2.ROTATE_90_CLOCKWISE + elif rotate == cv2.ROTATE_90_CLOCKWISE: + rotate = cv2.ROTATE_180 + elif rotate == cv2.ROTATE_180: + rotate = cv2.ROTATE_90_COUNTERCLOCKWISE + elif rotate == cv2.ROTATE_90_COUNTERCLOCKWISE: + rotate = None + while(cap.isOpened()): # Capture frame-by-frame ret, frame = cap.read() @@ -159,6 +188,10 @@ def change_temp_units(): loavg=loavg*256 avgtemp = loavg+hiavg + # rotate image, if requested + if not rotate is None: + imdata = cv2.rotate(imdata, rotate) + # Convert the real image to RGB bgr = cv2.cvtColor(imdata, cv2.COLOR_YUV2BGR_YUYV) #Contrast @@ -362,6 +395,9 @@ def change_temp_units(): if keyPress == ord('u'): #u to toggle units for temperature display change_temp_units() + if keyPress == ord('o'): #o to r(O)tate the image + change_rotation() + if keyPress == ord('q'): break capture.release()