У меня есть функция, которая считывает данные с инфракрасной тепловой камеры, обрабатывает данные и возвращает значение.В приведенном ниже коде возвращается минимальная обнаруженная температура.Эта функция требует значительных вычислительных ресурсов, поэтому я хочу запустить ее в отдельном потоке.
В приведенном ниже примере у меня есть класс, который запускает поток.Это работает один раз.Он читает датчик и возвращает темп.Но он никогда не запускает функцию снова.Он продолжает возвращать одно и то же значение температуры, даже если я изменяю вход датчика.Функция отлично работает сама по себе в отдельной программе и постоянно обновляет временные значения.
Я хочу, чтобы функция выполнялась в потоке, потому что я также играю звуки и управляю светодиодами.
Как мнезаставить функцию запускаться несколько раз в потоке, чтобы я мог непрерывно или периодически получать временные значения в основном потоке?
Я пытался использовать класс потока, но я должен что-то делать не так.Я также пытался использовать очередь, но никогда не получал никаких данных для возврата.
import queue
import sys
import pygame
import cv2
import random
import math
import colorsys
import time
from rpi_ws281x import *
from PIL import Image
import numpy as np
import threading
sys.path.insert(0, "/home/pi/irpython/build/lib.linux-armv7l-3.5")
import MLX90640 as mlx
# IR Function
def irCounter():
while True:
img = Image.new( 'L', (24,32), "black") # make IR image
mlx.setup(8) #set frame rate of MLX90640
f = mlx.get_frame()
mlx.cleanup()
for x in range(24):
row = []
for y in range(32):
val = f[32 * (23-x) + y]
row.append(val)
img.putpixel((x, y), (int(val)))
# convert raw temp data to numpy array
imgIR = np.array(img)
## Threshold the -40C to 300 C temps to a more human range
# Sensor seems to read a bit cold, calibrate in final setting
rangeMin = 6 # low threshold temp in C
rangeMax = 20 # high threshold temp in C
# Apply thresholds based on min and max ranges
depth_scale_factor = 255.0 / (rangeMax-rangeMin)
depth_scale_beta_factor = -rangeMin*255.0/(rangeMax-rangeMin)
depth_uint8 = imgIR*depth_scale_factor+depth_scale_beta_factor
depth_uint8[depth_uint8>255] = 255
depth_uint8[depth_uint8<0] = 0
depth_uint8 = depth_uint8.astype('uint8')
# increase the 24x32 px image to 240x320px for ease of seeing
bigIR = cv2.resize(depth_uint8, dsize=(240,320), interpolation=cv2.INTER_CUBIC)
# Normalize the image
normIR = cv2.normalize(bigIR, bigIR, 0, 255, cv2.NORM_MINMAX, cv2.CV_8U)
# Use a bilateral filter to blur while hopefully retaining edges
brightBlurIR = cv2.bilateralFilter(normIR,9,150,150)
# Threshold the image to black and white
retval, threshIR = cv2.threshold(brightBlurIR, 210, 255, cv2.THRESH_BINARY)
# Define kernal for erosion and dilation and closing operations
kernel = np.ones((5,5),np.uint8)
erosionIR = cv2.erode(threshIR,kernel,iterations = 1)
dilationIR = cv2.dilate(erosionIR,kernel,iterations = 1)
closingIR = cv2.morphologyEx(dilationIR, cv2.MORPH_CLOSE, kernel)
# Detect countours
contours, hierarchy = cv2.findContours(closingIR, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
# Get the number of contours ( contours count when touching edge of image while blobs don't)
#ncontours = str(len(contours))
ncontours = max(f)
# Show images in window during testing
#cv2.imshow("Combined", closingIR)
return ncontours
cv2.waitKey(1)
#initialize pygame
pygame.init()
pygame.mixer.init()
pygame.mixer.set_num_channels(30)
print("pygame initialized")
# assign sound chennels for pygame
channel0 = pygame.mixer.Channel(0)
channel1 = pygame.mixer.Channel(1)
channel2 = pygame.mixer.Channel(2)
channel3 = pygame.mixer.Channel(3)
channel4 = pygame.mixer.Channel(4)
# load soundfiles
echoballs = pygame.mixer.Sound("echo balls bounce.ogg")
organbounce = pygame.mixer.Sound("ORGAN BOUNCE.ogg")
jar = pygame.mixer.Sound("jar.ogg")
garland = pygame.mixer.Sound("GARLAND.ogg")
dribble= pygame.mixer.Sound("dribble.ogg")
# initializing sounds list
soundsList = [echoballs, organbounce, jar, garland, dribble]
# use random.sample() to shuffle sounds list
shuffledSounds = random.sample(soundsList, len(soundsList))
IRcount = 0 # for testing only
pygame.display.set_mode((32, 8)) # need display for keyboard input
# LED strip configuration:
LED_COUNT = 256 # Number of LED pixels.
LED_PIN = 18 # GPIO pin connected to the pixels (18 uses PWM!).
#LED_PIN = 10 # GPIO pin connected to the pixels (10 uses SPI /dev/spidev0.0).
LED_FREQ_HZ = 800000 # LED signal frequency in hertz (usually 800khz)
LED_DMA = 10 # DMA channel to use for generating signal (try 10)
LED_BRIGHTNESS = 100 # Set to 0 for darkest and 255 for brightest
LED_INVERT = False # True to invert the signal (when using NPN transistor level shift)
LED_CHANNEL = 0 # set to '1' for GPIOs 13, 19, 41, 45 or 53
# Define functions which animate LEDs in various ways.
plasmaTime = 0.0 # time
plasmaSpeed = 0.5 # speed of time
def sineLED1 ():
h = 8
w = 32
out = [ Color( 0, 0, 0 ) for x in range( h * w ) ]
plasmaBright = 100.0
for x in range( h ):
for y in range( w ):
hue = ((128+(128*math.sin(y + plasmaTime/ 8))))/256
hsv = colorsys.hsv_to_rgb(.5, 1,hue )
if y % 2 == 0: #even
out[ x + (h * y)] = Color( *[ int( round( c * plasmaBright ) ) for c in hsv ] )
else: #odd
out[ (y * h) + (h -1 -x) ] = Color( *[ int( round( c * plasmaBright ) ) for c in hsv ] )
for i in range( 0, strip.numPixels(), 1 ):# iterate over all LEDs - range(start_value, end_value, step)
strip.setPixelColor(i, out[ i ]) # set pixel to color in picture
strip.show()
# Threading class to get temp from IR function
class TempTask:
def __init__(self):
self.ir_temp = 0
self.thread = threading.Thread(target=self.update_temp)
def update_temp(self):
self.ir_temp = irCounter()
def start(self):
self.thread.start()
# Main program logic follows:
if __name__ == '__main__':
# start thread
task = TempTask()
task.start()
# Create NeoPixel object with appropriate configuration.
strip = Adafruit_NeoPixel(LED_COUNT, LED_PIN, LED_FREQ_HZ, LED_DMA, LED_INVERT, LED_BRIGHTNESS, LED_CHANNEL)
# Intialize the library (must be called once before other functions).
strip.begin()
print ('Press Ctrl-C to quit.')
try:
while True:
#simulate increase / decreat of people count from IRsensor for testing until irCounter function non-blocking
events = pygame.event.get()
for event in events:
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
IRcount -= 1
print(IRcount)
if event.key == pygame.K_RIGHT:
IRcount += 1
print(IRcount)
break
if IRcount == 0:
print(task.ir_temp) # print temp from sensor, only prints first time function runs
sineLED1()
plasmaTime = plasmaTime + plasmaSpeed # increment time
if pygame.mixer.Channel(0).get_busy() == False: channel0.play(shuffledSounds[0],loops = -1)
elif IRcount == 1:
sineLED1()
plasmaTime = plasmaTime + plasmaSpeed # increment time
if pygame.mixer.Channel(1).get_busy() == False: channel1.play(shuffledSounds[1],loops = -1)
elif IRcount == 2:
sineLED1()
plasmaTime = plasmaTime + plasmaSpeed # increment time
if pygame.mixer.Channel(2).get_busy() == False: channel2.play(shuffledSounds[2],loops = -1)
elif IRcount == 3:
sineLED1()
plasmaTime = plasmaTime + plasmaSpeed # increment time
if pygame.mixer.Channel(3).get_busy() == False: channel3.play(shuffledSounds[3],loops = -1)
elif IRcount == 4:
sineLED1()
if pygame.mixer.Channel(4).get_busy() == False: channel4.play(shuffledSounds[4],loops = -1)
except KeyboardInterrupt:
colorWipe(strip, Color(0,0,0), 1)
pygame.mixer.stop()
Я искал на форумах и пробовал много вещей, но не знаю, что делать дальше.
Здесьэто фрагмент из полного кода выше, где я делаю класс потока и запускаю поток
class TempTask:
def __init__(self):
self.ir_temp = 0
self.thread = threading.Thread(target=self.update_temp)
def update_temp(self):
self.ir_temp = irCounter()
def start(self):
self.thread.start()
# Main program logic follows:
if __name__ == '__main__':
# start thread
task = TempTask()
task.start()
Любая помощь или предложения о том, что делать дальше, очень ценится.Заранее спасибо.