After reading this, I tried the accepted answer, that gives a python script using cv to get an image from the webcam and calculate the brightness that will be applied to the screen.
When I tried it, though, the libraries just seemed to not work. Apparently, since the time that answer was posted (in 2011), changes were made to cv and highgui, for example, is not referenced anymore. I tried to get equivalences and somehow make an workaround, but it seems to be poorly documented or my problem is just too specific. Already searched here about it with no luck.
Here is my slightly modified version of the script:
import opencv
import opencv.highgui
import time
import commands
def get_image():
image = opencv.highgui.cvQueryFrame(camera)
return opencv.adaptors.Ipl2PIL(image)
camera = opencv.highgui.cvCreateCameraCapture(-1)
while 1:
image = get_image()
image.thumbnail((32, 24, ))
image = tuple(ord(i) for i in image.tostring())
x = int((int((max(image) / 256.0) * 10) + 1) ** 0.5 / 3 * 10)
cmd = ("sudo su -c 'echo " + str(x) +
" > /sys/devices/virtual/backlight/acpi_video0/brightness'")
status, output = commands.getstatusoutput(cmd)
assert status is 0
(had to change opencv to cv because even with python-opencv installed opencv couldn't be found).
Any light?
Related
Question in short:
We have a specific png image, where searching the datamatrix codes on a given location with the help of pylibdmtx library. At that specified location (given xmin, ymin, xmax, ymax coordinates in the code), we crop the image, rescale and send to the library to decode. but getting assertion error from dmtxdecodescheme.c, and program halts. we wish to neglect the error (return "?????" if possible), but try/except not working, and no way to escape.
Details:
This kind of error had never happened before, only on this specific png image, and given specific coordinates & SCALER value.
Uploaded the image at: https://easyupload.io/3yioro , because i can't upload to stackoverflow due to size constraints (3.1 Mb is over the 2Mb limit)
if i crop or convert image to another extension, error doesn't reproduce. this is really a rare and hard to duplicate error.
here is the simplified code, where you search only 1 given location:
from pylibdmtx.pylibdmtx import decode as decoder
import cv2
xmin = 755
ymin = 501
xmax = 830
ymax = 576
squareDim=150
SCALER=2
def bruteDMSearch(croppedImage):
try:
barcode = decoder(croppedImage)
#brute force cv2.threshold
threshh=50
while((not barcode) and (threshh<250)):
threshh=threshh+15
ret, thresholdy = cv2.threshold(croppedImage, threshh, 255, cv2.THRESH_BINARY)
barcode=decoder(thresholdy)
if(barcode):
code = ((barcode[0])[0]).decode("utf-8")
return code
else:
return "??????"
except:
return "?????"
img = cv2.imread("img.png",0)
sheight=int(img.shape[0]/SCALER)
swidth=int(img.shape[1]/SCALER)
smaller_img=cv2.resize(img,(swidth,sheight))
croppy = smaller_img[ymin:ymax,xmin:xmax]
#cv2.imshow("croppy",croppy)
#cv2.waitKey(0)
code = bruteDMSearch(croppy)
output is:
python3: dmtxdecodescheme.c:115: PushOutputWord: Assertion `value >= 0 && value < 256' failed.
Aborted (core dumped)
Your code worked as-is for me.
I got this output
Initially I had other problems with libdmtx.(This is an issue with libdmtx I faced and has no issue with your Python code)
I installed libdmtx using condas in win10. But during runtime I got FileNotFoundError: Could not find module 'libdmtx-64.dll'
then I built the library from https://github.com/dmtx/libdmtx and got release mode dmtx.dll. renamed this dll to libdmtx-64.dll and placed in `C:\Users\balu\Miniconda3\Library\bin'.
Note: if QR decoding is your goal, check your old questions I have answered.
I managed to reproduce this issue on ubuntu 21.10 with libdmtx-dev 0.7.5-3 and pylibdmtx 0.1.9:
python: dmtxdecodescheme.c:128: PushOutputWord: Assertion `value >= 0 && value < 256' failed.
Aborted (core dumped)
Given that the library is written in C and the C module itself is throwing a segfault, the try-except logic will not help here. You will need to run this line:
barcode = decoder(croppedImage)
in a separate process (via subprocess or multiprocessing). Here is an example of how you'd use a decorator to run the decoder in a segfault-proof way via multiprocessing.
I have the exact same image processing code running on two different machines inside conda environments, and I expect them both to give identical results, but they don't. So I did a lot of digging and found that the PIL function Image.convert() is giving different outputs on the two machines for exactly the same input, which can be explained by the PIL version on one machine being 6.2.1, and on the other machine being 7.0.0.
Looking at the documentation of 6.2.1 and 7.0.0 though, absolutely nothing changed about the formula they use to convert RGB to L in Image.convert(). I cloned the git repo and checked the implementation diff and it seems nothing changed:
diff --git a/src/libImaging/Convert.c b/src/libImaging/Convert.c
index 60513c66..9f572254 100644
--- a/src/libImaging/Convert.c
+++ b/src/libImaging/Convert.c
## -44,7 +44,8 ##
#define L(rgb)\
((INT32) (rgb)[0]*299 + (INT32) (rgb)[1]*587 + (INT32) (rgb)[2]*114)
#define L24(rgb)\
- ((rgb)[0]*19595 + (rgb)[1]*38470 + (rgb)[2]*7471)
+ ((rgb)[0]*19595 + (rgb)[1]*38470 + (rgb)[2]*7471 + 0x8000)
+
#ifndef round
double round(double x) {
Note that for my conversion from RGB to L (8-bit), the change in the L24() macro above should be irrelevant.
I don't understand where the difference is coming from and would like to understand it. Can anyone with more PIL insight show how/why/where it changed? Is there any note in the documentation that I've missed that this was changed?
I am an "advanced beginner" in Python, but a relative newbie with the Raspberry Pi...
What I'm trying to do:
I'm trying to capture a frame from the RTSP stream from a Wyze Cam V2 and save the image to a file. My code works - most of the time. But sometimes it fails for long periods of time. After much experimentation and trial and error I have determined that it is more likely to fail when the camera is in the dark! This seems very consistent.
My Code:
This is not the code from my actual project - it is the code I have been using to troubleshoot.
import cv2
import imageio
class Camera:
def __init__(self, ipaddress):
self.ipaddress = ipaddress
print("About to create VideoStream")
self.vs = cv2.VideoCapture(ipaddress, cv2.CAP_FFMPEG)
self.vs.set(cv2.CAP_PROP_BUFFERSIZE, 3)
if self.vs.isOpened():
print("Successfully created")
self.vs.release()
else:
print("Unable to create")
def capture(self):
self.vs.open(self.ipaddress)
success, frame = self.vs.read()
self.vs.release()
if success:
print("Capture Success")
return frame
else:
print("Failed to capture")
print("VideoCapture isOpen is " + str(self.vs.isOpened()))
return None
def is_opened(self):
return self.vs.isOpened()
# In actual code CAMNAME is the camera's name, PASSWORD is the password
# and XXX.XXX.X.XXX is the ip address
camera = Camera("rtsp://CAMNAME:PASSWORD#XXX.XXX.X.XXX/live")
leave = False
while not leave:
frame = camera.capture()
if frame is None:
print("Frame is none")
print("VideoCapture isOpen is " + str(camera.is_opened()))
else:
print("Successful capture - writing to file")
frame_color = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)
imageio.imwrite("test.jpg", frame_color)
response = input("Capture again? ")
if len(response) == 0:
response = "y"
if response[0] == 'n':
leave = True
What I Have Tried:
The code works fine when run on Windows 10. So not directly a problem with the code. In fact, when the Pi is having trouble capturing, doing it at the same time on Windows works. So definitely the issue is the Pi interacting with OpenCV or the camera.
Since I had ++ trouble installing OpenCV:
I have tried re-installing it on a fresh install of the OS with PIP (sudo pip install opencv-contrib-python==4.1.0.25).
I tried to build OpenCV from scratch - took 2.5 days and failed miserably - likely I screwed up somewhere in the process, but don't feel like spending another 2 days doing this.
Finally I downloaded a Raspbian image with OpenCV pre-compiled (https://medium.com/#aadeshshah/pre-installed-and-pre-configured-raspbian-with-opencv-4-1-0-for-raspberry-pi-3-model-b-b-9c307b9a993a). All these install methods resulted in the same issues...
I have tried opening the VideoCapture without specifying cv2.CAP_FFMPEG. I feel like it was more reliable with this option.
I have tried leaving out the change in BUFFERSIZE. I'm not sure this line of code has any effect.
What I am Using:
Raspberry Pi Model B, Rev 2, 512 kb
Raspbian Stretch - though I have had the same issues with Buster.
Wyze Cam II "beta" firmware that provides RTSP support.
Python3
OpenCV 4.1.0 (cv2.version)
What happens:
I have been troubleshooting this intermittent problem for some time, and just today realized it always works with the garage (where the camera is located) is light, and fails when it is dark. (Which made the late night troubleshooting sessions so frustrating!)
I have had many problems in the past, but now the issue seems to be that if the garage (where the camera is located) is dark, the VideoCapture object will not be created (.isOpened() == False) or the read() method will return False, None.
I used to have a problem with read() returning an old image. I can tell it is old because the camera timestamps the captures. This is why I am always opening and closing the VideoCapture - I would rather it not return an image than return the wrong/old image.
In the past, with slightly different settings, I would get warnings on the screen either during the creation of the VideoCapture object, or during the read() command. These are usually along the lines of "[h264 # 0x1ea1780] error while decoding MB 78 67, bytestream -15". I have gotten different warnings but I don't have examples right now. If I get a warning, I often get a bad image.
I have also gotten images that are distorted - that bottom of the image (sometimes a few lines, sometimes more than half of the image) looks like it it is the same line of data over and over.
Hi I'm new to opencv(version 2.4.7) and using it in python 2.7.4. I always get this error
HIGHGUI ERROR: V4L/V4L2: VIDIOC_S_CROP
whenever I use the command
cam = cv2.VideoCapture(cam_id)
The code works fine otherwise even with the error. I'm trying to use this wireless camera and it shows an image which has a magenta and green colored grid structure. My question is why am I getting the error and this weird image. The code gives nice image on other system also on my system itself. gstreamer-properties also have clear picture. The code:
from cv2 import cv
import cv2
import sys
def main():
cam_id = 0
# parameter
for i, arg in enumerate( sys.argv ):
if i == 0: continue
else: cam_id = arg
cam = cv2.VideoCapture(cam_id)
cv2.namedWindow("window", cv.CV_WINDOW_AUTOSIZE)
running = True
while running:
try:
flag, img = cam.read()
if flag:
cv2.imshow("window", img)
cv2.waitKey(30)
except KeyboardInterrupt:
running = False
cv2.destroyWindow("window")
main()
Sorry to update so late, I had figured out solution of the issue long ago but forgot to answer it here. It required loading a library before running the code. Use of following commands should do the trick.
For 32bit system:
$ LD_PRELOAD=/usr/lib/i386-linux-gnu/libv4l/v4l2convert.so python filename.py
For 64bit system:
$ LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libv4l/v4l2convert.so python filename.py
If this doesn't work then try locating the file v4l2convert.so by using command,
$ locate v4l2convert.so
As the output you'll see different paths, now try LD_PRELOAD with different paths.
If one wishes to beep the speaker on Windows, Python 2 apparently provides a useful function: winsound.Beep(). The neat thing about this function is that it takes arguments specifying the exact frequency and duration of the beep. This is exactly what I want to do, except that I don't use Windows. So...
What are the nearest equivalents of winsound.Beep() for Linux and OS X [edit: macOS], bringing in as few dependencies as possible?
Please note that I want to be able to beep the speaker directly, not to play a sound file. Also, I need to be able to control the frequency and duration of the beep, so curses.beep() and print '\a' won't do. Lastly, I am aware that PyGame provides extensive sound capabilities, but given that I don't require any of PyGame's other functionality, that would seem like using a sledgehammer to crack a nut (and anyway, I'm trying to do away with dependencies as far as possible).
[Edited on 9 Feb 2023 to reflect the fact that OS X was renamed macOS a few years after this question was asked]
winsound is only for windows and I could not find any cross platform way to do this, other than print "/a". However, you cannot set the frequency and duration with this.
However, you can try the os.system command to do the same with the system command beep. Here is a snippet, which defines the function playsound in a platform independent way
try:
import winsound
except ImportError:
import os
def playsound(frequency,duration):
#apt-get install beep
os.system('beep -f %s -l %s' % (frequency,duration))
else:
def playsound(frequency,duration):
winsound.Beep(frequency,duration)
For more info, look at this blog
EDIT: You will need to install the beep package on linux to run the beep command. You can install by giving the command
sudo apt-get install beep
I found a potential solution here:
http://bytes.com/topic/python/answers/25217-beeping-under-linux
It involves writing directly to /dev/audio. Not sure how portable it is or if it even works at all - i'm not on a linux machine atm.
def beep(frequency, amplitude, duration):
sample = 8000
half_period = int(sample/frequency/2)
beep = chr(amplitude)*half_period+chr(0)*half_period
beep *= int(duration*frequency)
audio = file('/dev/audio', 'wb')
audio.write(beep)
audio.close()
This works on mac:
import numpy as np
import simpleaudio as sa
def sound(x,z):
frequency = x # Our played note will be 440 Hz
fs = 44100 # 44100 samples per second
seconds = z # Note duration of 3 seconds
# Generate array with seconds*sample_rate steps, ranging between 0 and seconds
t = np.linspace(0, seconds, seconds * fs, False)
# Generate a 440 Hz sine wave
note = np.sin(frequency * t * 2 * np.pi)
# Ensure that highest value is in 16-bit range
audio = note * (2**15 - 1) / np.max(np.abs(note))
# Convert to 16-bit data
audio = audio.astype(np.int16)
# Start playback
play_obj = sa.play_buffer(audio, 1, 2, fs)
# Wait for playback to finish before exiting
play_obj.wait_done()
sound(300,2)
sound(200,1)
The most light-weight cross-platform layer I can see is "PortAudio". This is used by R for instance in their package to wrap platform-specific driver calls into simple play/record of digitized waveforms as an array.
The good folk at M.I.T. produce a Python binding for this, but you will need to include the compiled .dll/.so for this to work. http://people.csail.mit.edu/hubert/pyaudio/
( libao is similar by Xiph the makers of Ogg/Vorbis , a wrapper pyao exists but this seems less widely used )
SoX is an excellent set of cross-platform tools with much more functionality for format conversion and reading files etc..
Using ctypes to make calls from Python to a driver is feasible but very messy, even the simplest legacy WinMM.
I've found 3 methods for Linux:
new method using the Linux evdev API, works with any user in the input group (example source code)
old method using fcntl and /dev/console (requires root priviledges) (example source code)
invoke the beep command directly with subprocess or os.system (slower and must be installed in the system).
See also my tone() function here with all the alternatives.