Display a stream images in Google Colab using OpenCV - python

I have a stream of images and have to display it in Google Colab notebook such that it looks like a video, But what I get is a image under image ...
from google.colab import drive
drive.mount('/content/drive')
# importing cv2
import cv2
import imutils
from google.colab.patches import cv2_imshow
from IPython.display import clear_output
import os
folder = r'/content/drive/images/'
for filename in os.listdir(folder) :
VALID_FORMAT = (".jpg", ".JPG", ".jpeg", ".JPEG", ".png", ".PNG")
if filename.upper().endswith(VALID_FORMAT):
path = folder + filename
image = cv2.imread(path)
# resize image
frame = imutils.resize(image, width=1200)
# show the image
cv2_imshow(frame)
cv2.waitKey(20)

I don't know if some function can display image in the same place.
But I have code which I used with cv2 to display frames from webcam as video.
Here reduced version.
imshow(name, image) creates <img id="name"> and replaces src/url with image converted to string base64 and browser shows it as image.
imshow() uses name to check if already exist <img id="name"> and it replaces previous image.
from IPython.display import display, Javascript
from google.colab.output import eval_js
from base64 import b64encode
import cv2
def imshow(name, img):
"""Put frame as <img src="data:image/jpg;base64,...."> """
js = Javascript('''
async function showImage(name, image, width, height) {
img = document.getElementById(name);
if(img == null) {
img = document.createElement('img');
img.id = name;
document.body.appendChild(img);
}
img.src = image;
img.width = width;
img.height = height;
}
''')
height, width = img.shape[:2]
ret, data = cv2.imencode('.jpg', img) # compress array of pixels to JPG data
data = b64encode(data) # encode base64
data = data.decode() # convert bytes to string
data = 'data:image/jpg;base64,' + data # join header ("data:image/jpg;base64,") and base64 data (JPG)
display(js)
eval_js(f'showImage("{name}", "{data}", {width}, {height})') # run JavaScript code to put image (JPG as string base64) in <img>
# `name` and `data` in needs `" "` to send it as text, not as name of variabe.
And here code which uses it to display image Lenna from Wikipedia.
import requests
import cv2
import numpy as np
import time
url = 'https://upload.wikimedia.org/wikipedia/en/7/7d/Lenna_%28test_image%29.png'
data = requests.get(url)
frame1 = cv2.imdecode(np.frombuffer( data.content, np.uint8), 1)
frame2 = cv2.cvtColor(frame1, cv2.COLOR_BGR2GRAY)
for _ in range(3):
imshow("temp", frame1)
time.sleep(1)
imshow("temp", frame2)
time.sleep(1)
EDIT
Display images in two "windows" using imshow("img1", ...) and imshow("img2", ...)
import os
import cv2
import imutils
import time
folder = r'/content/drive/images/'
VALID_FORMAT = (".JPG", ".JPEG", ".PNG")
for number, filename in enumerate(os.listdir(folder)):
if filename.upper().endswith(VALID_FORMAT):
path = os.path.join(folder, filename)
image = cv2.imread(path)
frame = imutils.resize(image, width=400)
number = number % 2
imshow(f"img{number}", frame)
time.sleep(1)

Related

TypeError: 'TiffImageFile' object is not subscriptable for erose an image

I have the following code
url = 'https://people.math.sc.edu/Burkardt/data/tif/venus2.tif'
and the following code to read the image
from PIL import Image
import requests
from io import BytesIO
response = requests.get(url)
img = Image.open(BytesIO(response.content))
img
k=3
SE= np.ones((k,k), dtype=np.uint8)
constant= (k-1)//2
m,n = (img.size[0], img.size[1])
imgErode= np.zeros((m,n), dtype=np.uint8)
#Erosion without using inbuilt cv2 function for morphology
for i in range(constant, m-constant):
for j in range(constant,n-constant):
temp= img[i-constant:i+constant+1, j-constant:j+constant+1]
product= temp*SE
imgErode[i,j]= np.min(product)
plt.imshow(imgErode,cmap="gray")
cv2.imwrite("Eroded3.png", imgErode)
and I get the following error
TypeError: 'TiffImageFile' object is not subscriptable
PIL doesn't create numpy.array but object PIL.Image and you have to convert it
img = np.asarray(img)
Other problem:
After converting you have to use img.shape instead of img.size to get height, width because img.size in numpy gives number of bytes.
from io import BytesIO
import requests
from PIL import Image
import numpy as np
import cv2
url = 'https://people.math.sc.edu/Burkardt/data/tif/venus2.tif'
response = requests.get(url)
img = Image.open(BytesIO(response.content))
print('type:', type(img))
img = np.asarray(img)
print('type:', type(img))
cv2.imshow('original', img)
cv2.waitKey(10)
k = 3
SE = np.ones((k, k), dtype=np.uint8)
constant = (k-1)//2
m, n = img.shape[0:2]
imgErode= np.zeros((m, n), dtype=np.uint8)
#Erosion without using inbuilt cv2 function for morphology
for i in range(constant, m-constant):
for j in range(constant, n-constant):
temp = img[i-constant:i+constant+1, j-constant:j+constant+1]
product = temp * SE
imgErode[i, j]= np.min(product)
cv2.imshow('converted', imgErode)
cv2.waitKey(10)
cv2.imwrite("Eroded3.png", imgErode)
#cv2.destroyAllWindows()
EDIT:
Loading image from url using only cv2
import requests
import numpy as np
import cv2
url = 'https://people.math.sc.edu/Burkardt/data/tif/venus2.tif'
response = requests.get(url)
arr = np.asarray(bytearray(response.content))#, dtype="uint8")
img = cv2.imdecode(arr, cv2.IMREAD_COLOR)
cv2.imshow('original', img)
cv2.waitKey(100)
You may also use module imageio to read directly from url:
import imageio
import cv2
url = 'https://people.math.sc.edu/Burkardt/data/tif/venus2.tif'
img = imageio.imread(url)
cv2.imshow('original', img)
cv2.waitKey(100)

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.

face recognition can't detect if image face is not on portrait

I try using face recognition from this link: face recognition
then modif the code like this, main.py:
#!/usr/bin/env python
import cgitb, cgi
cgitb.enable()
print("Content-Type: text/html;charset=utf-8")
print "Content-type:text/html\r\n\r\n"
import base64
import simplejson as json
import re
import face_recognition
import numpy as np
import io
from imageio import imread
from PIL import Image
import datetime
import os, errno
import shutil
params = cgi.FieldStorage()
now = datetime.datetime.now()
date = str(now)
date2 = date.replace(" ","")
img = params.getvalue('img')
data1 = json.loads(img)
data2 = data1['img2']['data']
numparray = data1['img1']
numparray2 = numparray.replace(" ", "+")
b=bytes(numparray2)
imgdata = base64.b64decode(b)
os.makedirs(date2)
with open(date2+"/img1.png", "wb") as f:
f.write(imgdata)
image = face_recognition.load_image_file(date2+'/img1.png')
try:
face_encode = face_recognition.face_encodings(image)[0]
#print("face_encode = ".format(face_encode))
except IndexError:
print("encode image failed")
quit()
known_faces = []
y = 1
for images in data2:
ir = images.replace(" ", "+")
ib = bytes(ir)
imagedata = base64.b64decode(ib)
x = str(y)
with open(date2+"/compare"+x+".png", "wb") as g:
g.write(imagedata)
compare = face_recognition.load_image_file(date2+"/compare"+x+".png")
try:
compare_encode = face_recognition.face_encodings(compare)[0]
#print("face_encode = ".format(face_encode))
except IndexError:
print("encode image compare failed")
quit()
known_faces.append(compare_encode)
y = y+1
results = face_recognition.face_distance(known_faces, face_encode)
datahasil = []
#hasilakhir = "{"
for i, face_distance in enumerate(results):
h = "{:.2}".format(face_distance, i)
#hasilakhir = hasilakhir+"compare{}"
datahasil.append(h)
hasilakhir = ','.join(datahasil)
shutil.rmtree(date2, ignore_errors=True)
print("{\"hasilcompare\" : \"" +hasilakhir+ "\"}")
the final result is compare between 2 image and give the score, in case photo of image is potrait compare is successfull, but when one of image is not on potrait (face not on potrait potision) or like face angle more than 90 degree, that give error message in catch encode failed..
i have try another way with face detection before sending 2 image to main.py to detect the image in face but when it can't detect faces i try to rotate the image untill the code detect face, but sometimes face detection can detect face with angle 90degree but in face recognition(main.py) still can't read the face.
code of rotate is here, rotate.py:import numpy as np
import cv2
from scipy import ndimage, misc
import os
from PIL import Image
face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
for counter in range (0, 4):
img = cv2.imread('img/1.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(gray, 1.3, 5)
if(len(faces) == 1):
i = False
print ("face found")
break
else:
print("no face found")
i = False
img = Image.open("img/1.jpg")
img.rotate(90).save("img/1.jpg")
Yes, I think this is the problem with the library. I tested it on the same image. Once after rotation and once on the original image. It does not detect in the rotated image, both the face_locations and face_encodings are empty lists.

How to convert image format between PIL opencv web and mongoDB?

I want to store image from web to MongoDB, but first I will check the image by opencv to make sure it is an Blood Test Report image, just like followiing snippet:
if 'imagefile' not in request.files:
abort(400)
imgfile = request.files['imagefile']
if imgfile.filename == '':
abort(400)
if imgfile:
#pil = StringIO(imgfile)
#pil = Image.open(pil)
img = cv2.imdecode(numpy.fromstring(imgfile.read(), numpy.uint8), cv2.CV_LOAD_IMAGE_UNCHANGED)
filtered = ImageFilter(image=img).filter()
if filtered is None:
return jsonify({"error": "please make sure your picture is perfect"})
# save to mongo
content = StringIO()
filtered.save(content, format="JPEG")
fid, filename= save_file(content,imgfile.name)
The ImageFilter accepts a opencv format image, and do something such as filtering, and then return a PIL image, and it succeed! then I save the PIL image to MongoDB, code like this:
def save_file(content, name):
# content = StringIO(f.read())
try:
mime = Image.open(content).format.lower()
if mime not in app.config['ALLOWED_EXTENSIONS']:
raise IOError()
except IOError:
abort(400)
c = dict(content=bson.binary.Binary(content.getvalue()),
filename=secure_filename(name), mime=mime)
db.files.save(c)
return c['_id'], c['filename']
And it succeed! Then i have another function to find a image by id from MongoDB, then I will use it to do OCR.
def get_report(fid):
try:
file = db.files.find_one(bson.objectid.ObjectId(fid))
if file is None:
raise bson.errors.InvalidId()
print(type(file['content']))
img = cv2.imdecode(numpy.fromstring(dumps(file['content']), numpy.uint8), cv2.CV_LOAD_IMAGE_UNCHANGED)
if img is None:
return jsonify({"error": "please make sure your picture is perfect"})
report_data = ImageFilter(image=img).ocr(22)
print report_data
if report_data is None:
return jsonify({"error": "can't ocr'"})
return jsonify(report_data)
except bson.errors.InvalidId:
flask.abort(404)
Again, I will use it in opencv format, so I will convert the bson.binary.Binary to opencv image, but it failed! because img always none by
img = cv2.imdecode(numpy.fromstring(dumps(file['content']), numpy.uint8), cv2.CV_LOAD_IMAGE_UNCHANGED)
So, my last question is what is the real image format in python, How i convert it in web mongodb opencv pil and memory!,Following is one method i tried, but it failed! I want to convert the Binary to PIL image use Image.frombytes first, then i convert the PIL to opencv. But error:ValueError: not enough image data
# -*- coding: utf-8 -*-
import os
from pymongo import MongoClient
import bson
from PIL import Image
from imageFilter import ImageFilter
import cv2
import numpy
from bson.json_util import dumps
db = MongoClient('localhost', 27017).test
file =db.files.find_one(bson.objectid.ObjectId("58454666a235ec451d3bf2e6"))
if file is None:
raise bson.errors.InvalidId()
print(type(file['content']))
# this is success, I use Flask Response
#return Response(file['content'], mimetype='image/' + file['mime'])
# file['content']是整个图片文件的二进制对象,也就是说是一个文件,不应该直接作为二进制数据传递给Image
Image.frombytes(mode='RGB',size=(1000,760),data=file['content'])
img = cv2.imdecode(numpy.fromstring(dumps(file['content']), numpy.uint8), cv2.CV_LOAD_IMAGE_UNCHANGED)
if img is None:
print "img is None"
# ImageFilter accept opencv img to process it by opencv
report_data = ImageFilter(image=img).ocr(22)
print report_data

Image shown twisted after PIL to QImage conversion

This block of code is to save the image data read from a byte array to the Image img
val = bytearray(message.msg)
size = re.split(r',', message.messageSize)
img = Image.new("L", (int(size[0]), int(size[1])), 0)
pix = img.load()
counter = 0
for y in range(int(size[1])):
for x in range(int(size[0])):
pix[x, y] = val[counter]
counter = counter + 1
Then if I img.save('test.png', 'PNG') and QPixmap('test.png'), it will display the image normally. But if I use the following method, the image would be twisted.(screenshot and image are attached to the hyperlinks below)
self.imgQ = ImageQt(img) # img is PIL Image type
img.save('test.png', 'PNG') # this will be success
pixMap = QtGui.QPixmap.fromImage(self.imgQ)
self.scene1.clear()
self.scene1.addPixmap(pixMap)
self.scene1.update()
self.viewMessage.fitInView(QRectF(0, 0, int(size[0]), int(size[1])), Qt.KeepAspectRatio)
after I implemented the code above, the image is shown twisted. But if I saved the image, the image looks correct.
[update] even if I use the PNG that I saved, it still twisted.
im = Image.open('hehe.png')
I have uploaded the PNG file here.

Categories

Resources