How can i send cv2.frames to a browser - python

I am trying to send a webcam image to browser using Python. Now, I send it using the following code:
def send_a_frame():
capture = cv2.VideoCapture(0)
frame = capture.read()[1]
cv2.imwrite("im1.png",frame)
cnt = open("im1.png","rb").read()
b64 = base64.encodestring(cnt)
html = "<html><img src='data:image/png;base64,"+base64 +"'></html"
send(html)
How can I save an image and reopen an image and convert to base64 with a single statement?

I had the same problem, in my case I was reading from video file but it should work. Use cv2.imencode() method. See the following code
def send_a_frame():
capture = cv2.VideoCapture(0)
frame = capture.read()[1]
cnt = cv2.imencode('.png',frame)[1]
b64 = base64.encodestring(cnt)
html = "<html><img src='data:image/png;base64,"+b64 +"'></html"
send(html)

Related

Python + OpenCV + Base64: Issue with converting frame to base64

I am trying to convert a video to frames and those frames to base64 strings. I am unable to do so and getting some exceptions. Below is my code:
import cv2
import base64
def footage_to_frame(video):
vidcap = cv2.VideoCapture(video)
success, frames = vidcap.read()
if success:
return frames
def frame_to_base64(frames):
with frames as frame:
frame_b64 = base64.b64encode(frame.read())
return frame_b64
The function calls to this method are:
frames = converter.footage_to_frame("/Users/myname/Desktop/video.mp4")
converter.frame_to_base64(frames)
Below is the error I get in console:
File "/Users/myname/Desktop/Test/src/service/converter.py", line 13, in frame_to_base64
with frames as frame:
AttributeError: __enter__
In function frame_to_base64(frames), frames is already a single image because VideoCapture.read returns a single image. Also it is a opencv image (numpy array) which is not something you can use "with" on.
def frame_to_base64(frame):
return base64.b64encode(frame)
If you want to read all frames of video, you should do something like:
import cv2
import base64
def footage_to_frame(video):
vidcap = cv2.VideoCapture(video)
frames = []
# read until no more frames exist in the video
while True:
success, frame = vidcap.read()
if (success):
frames.append(frame)
else:
# unable to read a frame
break
return frames
def frames_to_base64(frames):
frames_b64 = []
# iterate frames and convert each of them to base64
for frame in frames:
frames_b64.append(base64.b64encode(frame))
return frames_b64
Although depending on video length, you may experience memory problems.

Scraping all the images from a specific part of a webpage using BeautifulSoup

Object 'gallery' is what I got - how would I be able to just select the image urls without going a long way around.
Currently, I am doing the following
from bs4 import BeautifulSoup
from PIL import Image
import requests
gallery = soup.findAll(class_='gallery')
img_0 = gallery[0].find('img')
img_1 = gallery[1].find('img')
...
img_x = gallery[x].find('img')
img_url_0 = img_0['src']
img_url_1 = img_1['src']
...
img_url_x = img_x['src']
gallery_img_0 = Image.open(requests.get(img_url_0, stream = True).raw)
gallery_img_1 = Image.open(requests.get(img_url_1, stream = True).raw)
...
gallery_img_x = Image.open(requests.get(img_url_x, stream = True).raw)
where x is the length of the gallery iterable.
Perhaps a loop? :s
Thanks, CN
You can use nested loop to load all image and store them to a list. For example:
galleries = soup.findAll(class_='gallery')
all_images = []
for gallery in galleries:
for img in gallery.findAll('img'):
gallery_img = Image.open(requests.get(img['src'], stream = True).raw)
all_images.append(gallery_img)
# here, `all_images` contains all images
# ...

Receiving an image with Fast API, processing it with cv2 then returning it

I am trying to build an API which receives an image and does some basic processing on it, then returns an updated copy of it using Open CV and Fast API. So far, I have the receiver working just fine, but when I try to base64 encode the processed image and send it back my mobile front end times out.
As a debugging practice I've tried just printing the encoded string and making the API call using Insomnia, but after 5 solid minutes of printing data I killed the application. Is returning a base64 encoded string the right move here? Is there an easier way to send an Open CV image via Fast API?
class Analyzer(BaseModel):
filename: str
img_dimensions: str
encoded_img: str
#app.post("/analyze", response_model=Analyzer)
async def analyze_route(file: UploadFile = File(...)):
contents = await file.read()
nparr = np.fromstring(contents, np.uint8)
img = cv2.imdecode(nparr, cv2.IMREAD_COLOR)
img_dimensions = str(img.shape)
return_img = processImage(img)
encoded_img = base64.b64encode(return_img)
return{
'filename': file.filename,
'dimensions': img_dimensions,
'encoded_img': endcoded_img,
}
#ZdaR 's comment did it for me. I was able to get the API call to work by re-encoding it to a PNG prior to encoding it to a base64 string.
The working code is as follows:
class Analyzer(BaseModel):
filename: str
img_dimensions: str
encoded_img: str
#app.post("/analyze", response_model=Analyzer)
async def analyze_route(file: UploadFile = File(...)):
contents = await file.read()
nparr = np.fromstring(contents, np.uint8)
img = cv2.imdecode(nparr, cv2.IMREAD_COLOR)
img_dimensions = str(img.shape)
return_img = processImage(img)
# line that fixed it
_, encoded_img = cv2.imencode('.PNG', return_img)
encoded_img = base64.b64encode(encoded_img)
return{
'filename': file.filename,
'dimensions': img_dimensions,
'encoded_img': endcoded_img,
}

Trying to encrypt video frames with RSA; getting garbage instead of original data after decrypting

I am writing a script to encrypt and decrypt video using RSA algo in python. Now I have extracted the frames from the video and encrypt each image individually and then combining the images to create a video. Then I am reading the frames of the encrypted video again and when I am applying the decryption key I am not getting back the original image. But when I am applying the same key on any image with which the video is made I am getting back the original image. let us say we have image1 which is encrypted and will be used to make the encrypted video when I am applying the key on this image I am getting back the original image. now I have image2 which is read from the encrypted video and if the keys are applied then it is giving a more encrypted image. Heres the code :
import cv2
import numpy
import os
import imageio
import time
from tkinter.filedialog import askopenfilename
from tkinter.ttk import *
from tkinter import *
from tkinter import filedialog
from tqdm import tqdm
from tkinter import messagebox
import subprocess
def load_image_decrypt(folder):
videofile = 'envid.avi'
try:
if not os.path.exists('Dedata'):
os.makedirs('Dedata')
except OSError:
messagebox.showinfo('Error Occured', 'Error: Creating directory of decrypted data')
vid_to_image(videofile)
for filename1 in tqdm(os.listdir(folder)):
imgV = imageio.imread(os.path.join(folder, filename1), format='PNG-FI')
if imgV is not None:
RGBdecryption(imgV, filename1)
else:
break
vidname = 'devid.avi'
image_to_vid(dedata2, vidname)
messagebox.showinfo('Finish!', 'Decryption Done succesfully!')
def RGBdecryption(img, filename):
img1 = img
img = img.astype(numpy.uint16)
img1= img1.tolist()
for i1 in tqdm(range(len(img1))):
for j1 in (range(len(img1[i1]))):
for k1 in (range(len(img1[i1][j1]))):
x1 = img1[i1][j1][k1]
x1 = pow(x1,16971,25777)
img1[i1][j1][k1] = x1
img1 = numpy.array(img1).astype(numpy.uint16)
name = './Dedata/'+str(filename)
imageio.imwrite(name, img1, format='PNG-FI')
def vid_to_image(filename):
# Playing video from file:
cap = cv2.VideoCapture(filename)
try:
if not os.path.exists('data'):
os.makedirs('data')
messagebox.showinfo('Info!', 'Data directory is created where the frames are stored')
except OSError:
print ('Error: Creating directory of data')
currentFrame = 0
while(True):
# Capture frame-by-frame
ret, frame = cap.read()
if not ret:
break
# Saves image of the current frame in jpg file
name = './data/frame' + str(currentFrame) + '.png'
print ('Creating...' + name)
imageio.imwrite(name, frame,format='PNG-FI')
# To stop duplicate images
currentFrame += 1
# When everything done, release the capture
cap.release()
cv2.destroyAllWindows()
def image_to_vid(folder, vidname): #the code which is creating a video out of images stored in the folder
image_folder = folder
video_name = vidname
sort_image = []
images = [img for img in os.listdir(image_folder) if img.endswith(".png")]
print(images)
print('\n\n')
for i in range(0,1000):
for j in range(len(images)):
name = 'frame' + str(i) + '.png'
if ((str(images[j])) == str(name)):
sort_image.append(images[j])
print(sort_image)
frame = cv2.imread(os.path.join(image_folder, sort_image[0]))
height, width, layers = frame.shape
video = cv2.VideoWriter(video_name, 0, 29, (width,height)) #29 is the fs of the original video and I don't know what the 0 is for
for image in sort_image:
video.write(cv2.imread(os.path.join(image_folder, image)))
cv2.destroyAllWindows()
video.release()
data = './data'
load_image_decrypt(data)
I do not know where I am getting it wrong. I am new to opencv and video processing. Any help will be appreciated. Thank you.
Video frames are subject to lossy compression. So you cannot feed a codec some binary data under the guise of images, encode it and expect to get exactly the same binary data back when playing the resulting video.
Your best bet is to encrypt the video file as a whole as per Encryption of video files? or How can I Encrypt Video in Real Time?. It will need to be decrypted to be playable; this is apparently what OSX's "content protection" does, encrypting and decrypting data transparently.
A (paywalled) IEEE article Video Encryption Based on OpenCV - IEEE Conference Publication says they applied an Arnold Transform to image data. It is a transposition cipher and as such, can be broken. Its main strength seems to rather be that it makes content unintelligible in regular playback, and it preserves image characteristics critical for video codecs (lighting, frame differences) and doesn't require the exact ciphertext for decryption, so it's not damaged beyond repair by the lossy compression.

python selenium screenshot captcha image

i want to take screenshot and crop only the captcha image, im write this code : http://pastebin.com/Hqau6kRD :
elem = driver.find_element_by_css_selector("#imagecpt")
loc = elem.location
size = elem.size
left = loc['x']
top = loc['y']
width = size['width']
height = size['height']
box = (int(left), int(top), int(left+width), int(top+height))
screenshot = driver.get_screenshot_as_png()
img = Image.open(StringIO.StringIO(screenshot))
area = img.crop(box)
area.save('screenshot.png', 'PNG')
the image saved is complete black, where im wrong ?
Yeah. For Python3 it will be like:
...
from io import BytesIO
...
screenshot = driver.get_screenshot_as_base64()
img = Image.open(BytesIO(base64.b64decode(screenshot))
...
I'm assuming you are using the Image module from PIL library.
Try getting the base64 value, decode it and then pass it as a parameter to the open() method.
...
screenshot = driver.get_screenshot_as_base64()
img = Image.open(StringIO.StringIO(base64.b64decode(screenshot))
...

Categories

Resources