Python: While loop updating LCD display - python

I'm fairly new to Python although I do have some understanding of programming.
I am currently using Python 3 on a Raspberry Pi with an LCD display connected to it.
I can output to the display using the PIL library and the examples that came with the display.
What I am trying to do is display a value that updates over a period of time.
To break this down I created a while loop that displays a number, sleeps for 3 seconds, increments the number and then runs back through the loop checking the integer is not greater than 10.
However, the screen never updates the integer. To make sure it’s incrementing and testing correctly I put a print statement to the console and can see it incrementing.
I'm assuming it’s something to do with the while loop not refreshing the display but can't figure it out. Sample code below. Any help appreciated.
#!/usr/bin/python
# -*- coding: UTF-8 -*-
#import chardet
import os
import sys
import time
import logging
import spidev as SPI
sys.path.append("..")
from lib import LCD_2inch4
from PIL import Image,ImageDraw,ImageFont
# Raspberry Pi pin configuration:
RST = 27
DC = 25
BL = 18
bus = 0
device = 0
i = 0
logging.basicConfig(level=logging.DEBUG)
try:
# display with hardware SPI:
disp = LCD_2inch4.LCD_2inch4()
# Initialize library.
disp.Init()
# Clear display.
disp.clear()
# Create blank image for drawing.
image1 = Image.new("RGB", (disp.width, disp.height ), "WHITE")
draw = ImageDraw.Draw(image1)
logging.info("draw point")
while i <10:
test_var = "some text"
draw.rectangle([(0,65),(140,100)],fill = "WHITE")
draw.text((5, 68), test_var, fill = "BLACK")
draw.text((5,150), str(i), fill = "BLACK")
draw = ImageDraw.Draw(image1)
image1=image1.rotate(0)
disp.ShowImage(image1)
time.sleep(3)
i= i+1
print(i)
disp.clear()
disp.module_exit()
logging.info("quit:")
except IOError as e:
logging.info(e)
except KeyboardInterrupt:
disp.module_exit()
logging.info("quit:")
exit()

Related

Python : how to have preview of DSLR camera

I came here as I am lost.
I have a code which basically provides a preview on screen before a picture is taken. The code runs on 2 camera (it doesn't make sense I know).
Pi camera : for preview
DSLR camera : for taking the pictures
The scripts works as expected. The issue is that the PIcamera zoom is not aligned with the DSLR.
I know it is possible to get the DSLR preview on screen which would be better. However I don't know how to do it. As I am new to python, I read as much as I could. I read solution with VLC but I didn't understand the specificities. I read the gphoto2 help but got lost in the technical parts. Hence I'd highly appreciate if someone can help me out or point me to the correct direction.
The DSLR camera is a Canon EOS D60 which should be compatible for screen preview.
I attached below the code
from picamera import PiCamera
import time
from time import sleep
import logging
import sys
import gphoto2 as gp
import locale
photonr = 1
countdown = 5
FolderRaw='/home/pi/'
def TakePicture():
global rafale
try:
rafale +=1
except Exception as e:
rafale =1
camera1 = PiCamera()
locale.setlocale(locale.LC_ALL, '')
logging.basicConfig(
format='%(levelname)s: %(name)s: %(message)s', level=logging.WARNING)
callback_obj = gp.check_result(gp.use_python_logging())
camera2 = gp.Camera()
camera2.init()
i = 1
while i < photonr+1:
preview = camera1.start_preview()
preview.fullscreen = True
picture_time = time.strftime("%Y-%m-%d")
global image
image = picture_time+ '_' + str(rafale) + '_' + str(i)
if i == 1 :
countdown2 = countdown +1
else :
countdown2 = 3
for counter in range(countdown2, 0, -1):
camera1.annotate_text = str(counter)
camera1.annotate_text_size = 120
sleep(1)
camera1.annotate_text = ''
print('Capturing image')
file_path = camera2.capture(gp.GP_CAPTURE_IMAGE)
print('Camera file path: {0}/{1}'.format(file_path.folder, file_path.name))
target = FolderRaw+image +'.jpg'
print('Copying image to', target)
camera_file = camera2.file_get(
file_path.folder, file_path.name, gp.GP_FILE_TYPE_NORMAL)
camera_file.save(target)
#camera.capture(FolderRaw+image +'.jpg')
camera1.stop_preview()
print ("Raw picture taken and saved on " + image )
i += 1
camera1.close()
camera2.exit()
TakePicture()
Thank you beforehand for any tips/direction/help

Pytesseract really slow

so I'm trying to read out text from MS Teams and use that text to make inputs on the keyboard.
Right now, I work with the threading module to have one thread for the input and one thread for the image_to_string. Following is the function for the image_to_string.
def imToString():
global message
print("Image getting read")
pytesseract.pytesseract.tesseract_cmd ='C:\\Users\\gornicec\\AppData\\Local\\Programs\\Tesseract-OCR\\tesseract.exe'
while(True):
print("preIMGgrab")
cap = ImageGrab.grab(bbox=(177, 850, 283, 881))
grayCap = cv2.cvtColor(np.array(cap), cv2.COLOR_BGR2GRAY)
print("postIMGgrab")
t = time.perf_counter()
print("preMSG" + str(t))
message = pytesseract.image_to_string(
grayCap,
lang ='deu',config='--psm 6')
print(str(message) + "was read" + str(time.perf_counter() - t))
I don't know how but it takes about 8 seconds to read an image thats 1000 pixels big. I need this to be at highest 2 seconds. I'll add the whole code at the end. If there is any way to make it faster or to do it differently please tell me so.
WHOLE CODE:
import numpy as np
import time
import pytesseract
from win32gui import GetWindowText, GetForegroundWindow
import win32api
import cv2
import pyautogui
from PIL import ImageGrab
import threading
from ahk import AHK
import keyboard
message = ""
ahk = AHK(executable_path='C:\\Program Files\\AutoHotkey\\AutoHotkey.exe')
def Controls():
global message
while True:
booleanVal = True
if booleanVal:
#imToString()
print("message")
#print("rechts" in message.lower())
#print(f'LÄNGE: {len(message)}')
if "vorne" in message.lower():
# Control(message, 'w')
ahk.key_press('w')
#message = ""
if "hinten" in message.lower():
# Control(message, 's')
ahk.key_press('s')
#message = ""
if "links" in message.lower():
# Control(message, 'a')
ahk.key_press('a')
#message = ""
if "rechts" in message.lower():
# Control(message, 'd')
#print("HAHAHA")
ahk.key_press('d')
#message = ""
if "greif" in message.lower():
ahk.key_press('space')
#message = ""
time.sleep(0.5)
#IMGTOSTRING---
controls = threading.Thread(target=Controls)
controls.start()
grab = threading.Thread(target=imToString)
grab.start()
pytesseract is not suit for large amount of images or images that are already in memory, its write them to a file and then pass the file path to tesseract cli, if you want to improve the performance of you script try using library that works directly with tesseract api.
like this: https://pypi.org/project/tess-py-api/

python, cv2.imshow(), raspberryPi and a black screen

Currently trying write code with a GUI which will allow for toggling on/off image processing. Ideally the code will allow for turning on/off window view, real time image processing (pretty basic), and controlling an external board.
The problem I'm having revolves around the cv2.imshow() function. A few months back I made a push to increase processing rates by switching from picamera to cv2 where I can perform more complex computations like background subtraction without having to call python all the time. using the bcm2835-v4l2 package, I was able to pull images directly from the picamera using cv2.
fast forward 6 months and while trying to update the code, I find that the function cv2.imshow() does not display correctly anymore. I thought it might be a problem with bcm2835-v4l2 but tests using matplotlib show that the connection is fine. it appears to have everything to do with cv2.imshow() or so I guess.
I am actually creating a separate thread using the threading module for image capture and I am wondering if this could be the culprit. I don't think so though as typing in the commands
import cv2
camera = cv2.VideoCapture(0)
grabbed,frame = camera.read()
cv2.imshow(frame)
produces the same black screen
Down below is my code I am using (on the RPi3) and some images show the error and what is expected.
as for reference here are the details about my system
Raspberry pi3
raspi stretch
python 3.5.1
opencv 3.4.1
Code
import cv2
from threading import Thread
import time
import numpy as np
from tkinter import Button, Label, mainloop, Tk, RIGHT
class GPIOControllersystem:
def __init__(self,OutPinOne=22, OutPinTwo=27,Objsize=30,src=0):
self.Objectsize = Objsize
# Build GUI controller
self.TK = Tk() # Place TK GUI class into self
# Variables
self.STSP = 0
self.ShutdownVar = 0
self.Abut = []
self.Bbut = []
self.Cbut = []
self.Dbut = []
# setup pi camera for aquisition
self.resolution = (640,480)
self.framerate = 60
# Video capture parameters
(w,h) = self.resolution
self.bytesPerFrame = w * h
self.Camera = cv2.VideoCapture(src)
self.fgbg = cv2.createBackgroundSubtractorMOG2()
def Testpins(self):
while True:
grabbed,frame = self.Camera.read()
frame = self.fgbg.apply(frame)
if self.ShutdownVar ==1:
break
if self.STSP == 1:
pic1, pic2 = map(np.copy,(frame,frame))
pic1[pic1 > 126] = 255
pic2[pic2 <250] = 0
frame = pic1
elif self.STSP ==1:
time.sleep(1)
cv2.imshow("Window",frame)
cv2.destroyAllWindows()
def MProcessing(self):
Thread(target=self.Testpins,args=()).start()
return self
def BuildGUI(self):
self.Abut = Button(self.TK,text = "Start/Stop System",command = self.CallbackSTSP)
self.Bbut = Button(self.TK,text = "Change Pump Speed",command = self.CallbackShutdown)
self.Cbut = Button(self.TK,text = "Shutdown System",command = self.callbackPumpSpeed)
self.Dbut = Button(self.TK,text = "Start System",command = self.MProcessing)
self.Abut.pack(padx=5,pady=10,side=RIGHT)
self.Bbut.pack(padx=5,pady=10,side=RIGHT)
self.Cbut.pack(padx=5,pady=10,side=RIGHT)
self.Dbut.pack(padx=5,pady=10,side=RIGHT)
Label(self.TK, text="Controller").pack(padx=5, pady=10, side=RIGHT)
mainloop()
def CallbackSTSP(self):
if self.STSP == 1:
self.STSP = 0
print("stop")
elif self.STSP == 0:
self.STSP = 1
print("start")
def CallbackShutdown(self):
self.ShutdownVar = 1
def callbackPumpSpeed(self):
pass
if __name__ == "__main__":
GPIOControllersystem().BuildGUI()
Using matplotlib.pyplot.imshow(), I can see that the connection between the raspberry pi camera and opencv is working through the bcm2835-v4l2 connection.
However when using opencv.imshow() the window result in a blackbox, nothing is displayed.
Update: so while testing I found out that when I perform the following task
import cv2
import matplotlib
camera = cv2.VideoCapture(0)
grab,frame = camera.read()
matplotlib.pyplot.imshow(frame)
grab,frame = camera.read()
matplotlib.pyplot.imshow(frame)
update was solved and not related to the main problem. This was a buffering issue. Appears to have no correlation to cv2.imshow()
on a raspberry you should work with
from picamera import PiCamera
checkout pyimagesearch for that

Raspberry Pi - Python & Flask web control with Adafruit DotStar LEDS

apologies if this isn't the right place to ask, but I did some searching and couldn't find much to point me in the right direction. I wasn't quite sure what to search for. I am a novice with python and programming in general, but usually can do enough googling and stealing other code snippets to get my projects running. However I'm at a bit of a roadblock here.
I need to control an Adafruit DotStar lightstrip with a flask web browser app. I've been able to get the flask app working, I've done a simple proof of concept with turning an LED on and off etc., and I can start my lightstrip script but the code I'm trying to run for the lightstrip needs to loop continuously and still be able to change "modes". I have several different images that display on the light strip and I would like to be able to select which one(s) is/are playing, but for now mainly I would just like to be able to start and stop a "shuffle all" mode. If I run the module in a while loop it just loops forever and I can't change the argument to a different "mode". I built a simple script based on Adafruit's DotStar library (specifically the image persistence of vision script, I'm just using PNG images as the map for the different lightstrip "shows").
It all currently works except it only runs each mode once obviously. I had it all in a while loop and it just looped the first selected mode forever and I was unable to turn it off or switch modes. I also thought maybe I should use multiprocessing, and I looked into getting that working, but I couldn't figure out how to stop a process once it started.
Here is the light strip script:
(the 'off' mode is just a black image. I'm sure theres a cleaner way to do this but I'm not sure on how to do that either)
import Image
from dotstar import Adafruit_DotStar
import random
def lightstrip(mode):
loopLength = 120 #loop length in pixels
fade = "/home/pi/lightshow/images/fade.png"
sparkle = "/home/pi/lightshow/images/sparkle.png"
steeplechase = "/home/pi/lightshow/images/steeplechase.png"
bump = "/home/pi/lightshow/images/bump.png"
spaz = "/home/pi/lightshow/images/spaz.png"
sine = "/home/pi/lightshow/images/sine.png"
bounce = "/home/pi/lightshow/images/bounce.png"
off = "/home/pi/lightshow/images/null.png"
numpixels = 30
datapin = 23
clockpin = 24
strip = Adafruit_DotStar(numpixels, 100000)
rOffset = 3
gOffset = 2
bOffset = 1
strip.begin()
if mode == 1:
options = [fade, sparkle, steeplechase, bump, spaz, sine, bounce]
print "Shuffling All..."
if mode == 2:
options = [bump, spaz, sine, bounce]
print "Shuffling Dance..."
if mode == 3:
options = [fade, sparkle, steeplechase]
print "Shuffling Chill..."
if mode == 0:
choice = off
print "Lightstrip off..."
if mode != 0:
choice = random.choice(options)
print "Loading..."
img = Image.open(choice).convert("RGB")
pixels = img.load()
width = img.size[0]
height = img.size[1]
print "%dx%d pixels" % img.size
# Calculate gamma correction table, makes mid-range colors look 'right':
gamma = bytearray(256)
for i in range(256):
gamma[i] = int(pow(float(i) / 255.0, 2.7) * 255.0 + 0.5)
# Allocate list of bytearrays, one for each column of image.
# Each pixel REQUIRES 4 bytes (0xFF, B, G, R).
print "Allocating..."
column = [0 for x in range(width)]
for x in range(width):
column[x] = bytearray(height * 4)
# Convert entire RGB image into column-wise BGR bytearray list.
# The image-paint.py example proceeds in R/G/B order because it's counting
# on the library to do any necessary conversion. Because we're preparing
# data directly for the strip, it's necessary to work in its native order.
print "Converting..."
for x in range(width): # For each column of image...
for y in range(height): # For each pixel in column...
value = pixels[x, y] # Read pixel in image
y4 = y * 4 # Position in raw buffer
column[x][y4] = 0xFF # Pixel start marker
column[x][y4 + rOffset] = gamma[value[0]] # Gamma-corrected R
column[x][y4 + gOffset] = gamma[value[1]] # Gamma-corrected G
column[x][y4 + bOffset] = gamma[value[2]] # Gamma-corrected B
print "Displaying..."
count = loopLength
while (count > 0):
for x in range(width): # For each column of image...
strip.show(column[x]) # Write raw data to strip
count = count - 1
And the main.py script for running the web app:
from flask import *
from lightshow import *
from multiprocessing import Process
import RPi.GPIO as GPIO
import Image
from dotstar import Adafruit_DotStar
import random
import time
app = Flask(__name__)
#app.route("/")
def hello():
return render_template('index.html')
#app.route("/lightstrip/1", methods=['POST'])
def shuffleall():
lightstrip(1)
return ('', 204)
#app.route("/lightstrip/2", methods=['POST'])
def shuffledance():
lightstrip(2)
return ('', 204)
#app.route("/lightstrip/3", methods=['POST'])
def shufflechill():
lightstrip(3)
return ('', 204)
#app.route("/lightstrip/0", methods=['POST'])
def off():
lightstrip(0)
return ('', 204)
if __name__ == "__main__":
app.run(host='0.0.0.0', debug=True)
Again I'm at a bit of a loss here, this may be simple fix or I may be approaching it totally wrong but any and all help would be appreciated. I am a complete beginner to approaching a problem like this. Thank you
Here's an example showing how to start and stop processes using multiprocessing and psutil. In this example the task_runner kills any running processes before starting a new one.
from flask import Flask
import multiprocessing
import psutil
app = Flask(__name__)
def blink(var):
while True:
# do stuff
print(var)
def task_runner(var):
processes = psutil.Process().children()
for p in processes:
p.kill()
process = multiprocessing.Process(target=blink, args=(var,))
process.start()
#app.route("/red")
def red():
task_runner('red')
return 'red started'
#app.route("/blue")
def blue():
task_runner('blue')
return 'blue started'
if __name__ == "__main__":
app.run()
For your question, the task_runner would look something like:
def task_runner(mode):
processes = psutil.Process().children()
for p in processes:
p.kill()
process = multiprocessing.Process(target=lightstrip, args=(mode,))
process.start()

Palette method using numpy

I am trying to apply the numpy palette method to an opencv processed video (references: this question and this tutorial ). I aim at replacing all frame pixels of a certain color range by another. The code below is an example that replaces black with green. Unfotunately, my code raises an error on line:
image[np.where((image==[0,0,0]).all(axis=2))]=green
the error: exceptions.ValueError:axis(=2) out of bounds
I am running python 2.7 with PyScripter, and I find it odd because the code did work before, and I did not make any major modification to it. Can someone please help me? I am quite stuck on this one...
My code:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
##IMPORTS
import cv2.cv as cv
import numpy as np
import time
##VARIABLES
#colors
green=[0,255,0]
##MAIN
#video file input
frames = raw_input('Please input video file:')
if not frames:
print "This program requires a file as input!"
sys.exit(1)
#create window
cv.NamedWindow("image", 1)
#File capture
vidFile = cv.CaptureFromFile(frames)
nFrames = int( cv.GetCaptureProperty( vidFile, cv.CV_CAP_PROP_FRAME_COUNT ) )
fps = cv.GetCaptureProperty( vidFile, cv.CV_CAP_PROP_FPS )
waitPerFrameInMillisec = int( 1/fps * 1000/1 )
#time adjustment, frame capture
for f in xrange( nFrames ):
frame = cv.QueryFrame( vidFile )
# create the images we need
image = cv.CreateImage (cv.GetSize (frame), 8, 3)
# copy the frame, so we can draw on it
if not frame:
break
else:
cv.Copy (frame, image)
#get pixel HSV colors
rows,cols=cv.GetSize(frame)
image=np.asarray(image)
image[np.where((image==[0,0,0]).all(axis=2))]=green
image=cv.fromarray(image)
#show the image
cv.ShowImage("image", image)
#quit command ESC
if cv.WaitKey(waitPerFrameInMillisec)==27:
break
else:
cv.WaitKey(waitPerFrameInMillisec) % 0x100
I solved it. In fact, the answer was not a modification of the line raising the exception, but rather on a modification of the arguments that were passed to this line. Indeed, it seems that the '[:,:]' arguments are required in opencv when converting cvMat to Numpy and back.
Here is the corrected code:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
##IMPORTS
import cv2.cv as cv
import numpy as np
##VARIABLES
#colors
green=[0,255,0]
##MAIN
#start video stream analysis
frames = raw_input('Please enter video file:')
if not frames:
print "This program requires a file as input!"
sys.exit(1)
# first, create the necessary windows
cv.NamedWindow ('image', cv.CV_WINDOW_AUTOSIZE)
#File capture
vidFile = cv.CaptureFromFile(frames)
nFrames = int( cv.GetCaptureProperty( vidFile, cv.CV_CAP_PROP_FRAME_COUNT ) )
fps = cv.GetCaptureProperty( vidFile, cv.CV_CAP_PROP_FPS )
waitPerFrameInMillisec = int( 1/fps * 1000/1 )
for f in xrange( nFrames ):
#time adjustment, frame capture
sec = f/fps
frame = cv.QueryFrame( vidFile )
# create the images we need
image = cv.CreateImage (cv.GetSize (frame), 8, 3)
# copy the frame, so we can draw on it
if not frame:
break
else:
cv.Copy (frame, image)
#Replace pixel colors
rows,cols=cv.GetSize(frame)
image=np.asarray(image[:,:])
image[np.where((image==[0,0,0]).all(axis=2))]=green
image=cv.fromarray(image[:,:])
#show the image
cv.ShowImage("image", image)
#quit command ESC
if cv.WaitKey(waitPerFrameInMillisec)==27:
break
else:
cv.WaitKey(waitPerFrameInMillisec) % 0x100
cv.DestroyAllWindows()

Categories

Resources