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
Related
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/
I am creating a raspberry pi timelapse camera encoding video with CV2 videowriter
Each image captured with picamera is added to the videowriter and once the intended number of images are taken the videowriter closes.
However - while this works for a few thousand images - it stops at some limit with a filesize of 366Mb which is now frustrating me and I ask you - the internet and hoard of coders to tell me why I am bad a coding and how to fix this - you must be tempted by this..
Here is my offering of garbage for you to laugh pitifully at
import os, cv2
from picamera import PiCamera
from picamera.array import PiRGBArray
from datetime import datetime
from time import sleep
now = datetime.now()
x = now.strftime("%Y")+"-"+now.strftime("%m")+"-"+now.strftime("%d")+"-"+now.strftime("%H")+"-"+now.strftime("%M") #string of dateandtimestart
print(x)
def main():
imagenum = 10000 #how many images
period = 1 #seconds between images
os.chdir ("/home/pi/t_lapse")
os.mkdir(x)
os.chdir(x)
filename = x + ".avi"
camera = PiCamera()
camera.resolution=(1920,1088)
camera.vflip = True
camera.hflip = True
camera.color_effects = (128,128) #makes a black and white image for IR camera
sleep(0.1)
out = cv2.VideoWriter(filename, cv2.cv.CV_FOURCC(*'XVID'), 30, (1920,1088))
for c in range(imagenum):
with PiRGBArray(camera, size=(1920,1088)) as output:
camera.capture(output, 'bgr')
imagec = output.array
out.write(imagec)
output.truncate(0) #trying to get more than 300mb files..
pass
sleep(period-0.5)
camera.close()
out.release()
if __name__ == '__main__':
main()
This example is a part of the whole code I've written (https://github.com/gchennell/RPi-PiLapse) which has an OLED display and buttons and selection of how many images as I have this all in an enclosure - the number of images seems to be limited to about 3000-4000 and then it just gives up and goes home... I tried adding the output.truncate(0)
I have also recreated this in python3 before you cry "BUT CV2.CV2.VIDEOWRITER!!!!" and that hasn't changed a thing - I'm missing something here...
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
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()
I'm trying to get the angle of the middle line in a domino. SimpleBlobDetector can find it, but it gives me an angle value of -1.
Does anyone know why that can be? and how can i fix that still using SimpleBlobDetector? and if SimpleBlobDetector is not an option, what else can i do to find the center and angle of these lines?
import numpy as np
import cv2
import os
import time
#from matplotlib import pyplot as plt
def main():
capWebcam = cv2.VideoCapture(0) # declare a VideoCapture object and associate to webcam, 0 => use 1st webcam
params = cv2.SimpleBlobDetector_Params()
params.filterByCircularity = True
params.minCircularity = 0.73
params2 = cv2.SimpleBlobDetector_Params()
params2.filterByInertia = True
params2.maxInertiaRatio = 0.3
# show original resolution
print "default resolution = " + str(capWebcam.get(cv2.CAP_PROP_FRAME_WIDTH)) + "x" + str(capWebcam.get(cv2.CAP_PROP_FRAME_HEIGHT))
capWebcam.set(cv2.CAP_PROP_FRAME_WIDTH, 320.0) # change resolution to 320x240 for faster processing
capWebcam.set(cv2.CAP_PROP_FRAME_HEIGHT, 240.0)
capWebcam.set(cv2.CAP_PROP_FPS, 1)
# show updated resolution
print "updated resolution = " + str(capWebcam.get(cv2.CAP_PROP_FRAME_WIDTH)) + "x" + str(capWebcam.get(cv2.CAP_PROP_FRAME_HEIGHT))
if capWebcam.isOpened() == False: # check if VideoCapture object was associated to webcam successfully
print "error: capWebcam not accessed successfully\n\n" # if not, print error message to std out
os.system("pause") # pause until user presses a key so user can see error message
return # and exit function (which exits program)
# end if
while cv2.waitKey(1) != 27 and capWebcam.isOpened(): # until the Esc key is pressed or webcam connection is lost
blnFrameReadSuccessfully, img = capWebcam.read() # read next frame
if not blnFrameReadSuccessfully or img is None: # if frame was not read successfully
print "error: frame not read from webcam\n" # print error message to std out
os.system("pause") # pause until user presses a key so user can see error message
break # exit while loop (which exits program)
det = cv2.SimpleBlobDetector_create(params)
det2 = cv2.SimpleBlobDetector_create(params2)
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
time.sleep(0.1)
keypts = det.detect(gray)
time.sleep(0.1)
keypts2 = det2.detect(gray)
print len(keypts)
print len(keypts2)
for l in keypts2:
print l.pt
print l.angle
time.sleep(0.3)
imgwk = cv2.drawKeypoints(gray, keypts, img,color= (200,0,139),flags=2)
time.sleep(0.1)
imgwk2 = cv2.drawKeypoints(img, keypts2, gray,color= (200,0,139),flags=2)
cv2.namedWindow("img", cv2.WINDOW_AUTOSIZE) # or use WINDOW_NORMAL to allow window resizing
cv2.imshow("img", img)
# hold windows open until user presses a key
cv2.destroyAllWindows()
return
###################################################################################################
if __name__ == "__main__":
main()
I'm not sure if SimpleBlob detector is the best for this, but have you looked at
Detect centre and angle of rectangles in an image using Opencv
It seems quite similar to you question, and seems to do very well at identifying the angle of the rectangles