getting the image from VideoCapture object using read() - python

I am reading a video frame by frame using:
vc = cv2.VideoCapture('test.avi')
and later on I check whether the frame has been read using:
if vc.isOpened():
rval,frame = vc.read()
else:
rval = False
Now the problem is , if I try to convert this frame to a numpy array using the following code:
PILImage = Image.fromstring("L",cv.GetSize(frame),frame.tostring())
NumPyArray = np.array(PILImage)
I get an error saying:
CvArr argument 'arr' must be IplImage, CvMat or CvMatND. Use fromarray() to convert numpy arrays to CvMat or cvMatND
From Documentation of VideoCapture::read I found that it returns two things [retVal,Image] . How do I get the Image part only and how do I convert it to Numpy Array?
Further Info:
Basically the whole point in doing this is that ,I am trying to write a program which allows me to go through each frame of the video by pressing spacebar, and select a particular region from any frame and save it as a jpg. Here is the Code:
from ITMS import ITMS
import cv2
from cv2 import cv
import numpy as np
import matplotlib.pyplot as plt
import Image
import matplotlib.widgets as widgets
def onselect(eclick, erelease):
if eclick.ydata>erelease.ydata:
eclick.ydata,erelease.ydata=erelease.ydata,eclick.ydata
if eclick.xdata>erelease.xdata:
eclick.xdata,erelease.xdata=erelease.xdata,eclick.xdata
ax.set_ylim(erelease.ydata,eclick.ydata)
ax.set_xlim(eclick.xdata,erelease.xdata)
fig.canvas.draw()
def subImager(arr):
fig = plt.figure()
ax = fig.add_subplot(111)
plt_image=plt.imshow(arr,cmap="Greys_r")
rs=widgets.RectangleSelector(
ax, onselect, drawtype='box',
rectprops = dict(facecolor='red', edgecolor = 'red', alpha=0.2, fill=True))
plt.show()
cv2.namedWindow("preview")
vc = cv2.VideoCapture('test.avi')
if vc.isOpened():
rval,frame = vc.read()
else:
rval = False
while rval:
key = cv2.waitKey(30)
if key==32:
cv2.imshow("preview", frame)
NumPyArray=ITMS.CVtoNPArray(frame)
subImager(NumPyArray)
rval,frame = vc.read()
elif key==27:
break
cv2.destroyAllWindows()
ITMS Class:
from cv2 import cv
import cv2
import numpy as np
from PIL import Image
class ITMS:
def __init__(self):
pass
def CVtoNPArray(CVImage):
PILImage = Image.fromstring("L",cv.GetSize(CVImage),CVImage.tostring())
NumPyArray = np.array(PILImage)
return NumPyArray
CVtoNPArray=staticmethod(CVtoNPArray)

You are over-complicating things, the image returned in your frame name is already a numpy array. If you want to convert it to PIL, simply do Image.fromarray(frame).

Related

Arrays of object detected as int output

I would like to gain out the arrays of object detected using python and YOLOv5. I use:
import torch
import cv2
from matplotlib import pyplot as plt
import numpy as np
import uuid
import os
import time
model = torch.hub.load('ultralytics/yolov5', 'custom', path="C:\\Users\\Legion\\Desktop\\yolo\\yolov5\\runs\\train\\exp5\\weights\\last.pt", force_reload=True)
cap = cv2.VideoCapture(0)
while cap.isOpened():
ret, frame = cap.read()
results = model(frame)
cv2.imshow('YOLO', np.squeeze(results.render()))
if cv2.waitKey(10) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
How to get the arrays of objects detected and how to get them as integers, to provide comparison? F.e. If arrays [x,y] < [70,90] then ...
Thank you guys.
I have searched a lot and now I need specific idea how to get the results I need.

Dimming image in Python

I am trying to implement dimming method to dim a image by converting pixel values and using this equation X(new) = 0.5 * X(old)^2. I did some googling and but could not succeed. Here is my code:
import math
from PIL import Image
import numpy as np
from skimage import color, io
import matplotlib.pyplot as plt
def load(image_path):
out = plt.imread(image_path)
out = out.astype(np.float64) / 255
return out
def dim_image(image):
out = image.point(lambda x: x*0.5)
return out
def display(img):
# Show image
plt.figure(figsize = (5,5))
plt.imshow(img)
plt.axis('off')
plt.show()
image1 = load(image1_path)
image2 = load(image2_path)
display(image1)
display(image2)
new_image = dim_image(image1)
display(new_image)
You are trying to use .point on a numpy array, which doesn't exist. I assume you meant to reduce all color values by 50% to dim the image, in which case you should use np.dot (docs):
def dim_image(image):
out = np.dot(image, 0.5)
return out

im7 image files to openCV

Able to show the image through matplotlib, however unable to do it through cv2.imshow. The shape of the image is not consistent with opencv required formats. Require help on changing on changing it so it can be shown by the command cv2.imshow
test.jpg is a random jpg file from web
import numpy as np
import cv2
import matplotlib.pyplot as plt
import ReadIM
img = cv2.imread('test.jpg')
vbuff, vatts = ReadIM.extra.get_Buffer_andAttributeList('test.im7')
v_array, vbuff = ReadIM.extra.buffer_as_array(vbuff)
print (np.shape(v_array))
print (v_array[0])
print (np.shape(img))
# Showing image through matplotlib
plt.imshow(v_array[0])
plt.show()
#Showing image through cv2
cv2.imshow('image',v_array[0])
cv2.waitKey(0)
cv2.destroyAllWindows()
# Remove memory
#del(vbuff)
ReadIM.DestroyBuffer(vbuff)
ReadIM.DestroyAttributeListSafe(vatts)
test.im7
Normalizing the image to (0,255) will do the trick
img = cv2.normalize(img, None, 255,0,cv2.NORM_MINMAX,dtype = cv2.CV_8UC1)
cv2.imshow('image',img)

python bokeh: get image from webcam and show it in dashboard

I want to display an image - e.g. capture with the webcam - in bokeh. I tried image_url and image_rgba, but both are not working. Image_url is showing nothing, image_rgb shows something, but there seems to be some index shift.
# -*- coding: utf-8 -*-
from bokeh.plotting import figure, show
import scipy.misc
import cv2
import matplotlib.pyplot as plt
import os
# capture video frame from webcam
#vc = cv2.VideoCapture(1)
vc = cv2.VideoCapture(-0)
rval, frame = vc.read()
vc.release()
# show captured image (figure 1)
fig = plt.figure()
ax = plt.Axes(fig,[0,0,1,1])
ax.set_axis_off()
fig.add_axes(ax)
ax.imshow(frame)
plt.show()
# save captured image
scipy.misc.imsave('outfile.jpg', frame)
mypath = os.path.join(os.getcwd(),'outfile.jpg')
# 1. try using image_url ... not working (figure 2)
p = figure()
p.image_url(url=[mypath],x=[0],y=[1],w=[10],h=[10])
show(p)
# 2. try using image_rgba ... also not working (figure 3)
p = figure(x_range=(0,10), y_range=(0,10))
p.image_rgba(image=[frame], x=0, y=0, dw=10, dh=10)
show(p)
# 3. solution provided by #bigreddot ... flipped but also not working (figure4)
img = scipy.misc.imread(mypath)[::-1] # flip y-direction for Bokeh
p = figure(x_range=(0,10), y_range=(0,10))
p.image_rgba(image=[img], x=0, y=0, dw=10, dh=10)
show(p)
update: according to #bigreddot 's comment
figure 1
figure 2
figure 3
figure 4
the bokeh version I use is 0.13 the python version 3.6.0
After investigation, the return result from OpenCV is a Numpy array of bytes with shape (M, N, 3), i.e. RGB tuples. What Bokeh expects is a Numpy array of shape (M, N) 32-bit integers representing RGBA values. So you need to convert from one format to the other. Here is a complete example:
from bokeh.plotting import figure, show
import scipy.misc
import cv2
import os
import numpy as np
#vc = cv2.VideoCapture(1)
vc = cv2.VideoCapture(-0)
rval, frame = vc.read()
vc.release()
M, N, _ = frame.shape
img = np.empty((M, N), dtype=np.uint32)
view = img.view(dtype=np.uint8).reshape((M, N, 4))
view[:,:,0] = frame[:,:,0] # copy red channel
view[:,:,1] = frame[:,:,1] # copy blue channel
view[:,:,2] = frame[:,:,2] # copy green channel
view[:,:,3] = 255
img = img[::-1] # flip for Bokeh
p = figure()
p.image_rgba(image=[img],x=0,y=0, dw=10, dh=10)
show(p)
Generates:

Using img_to_graph from Sklearn

I have the following code:
import cv2
import matplotlib.pyplot as plt
import numpy as np
from scipy import ndimage
from sklearn.feature_extraction import image
from sklearn.cluster import spectral_clustering
image = cv2.imread("/home/facu/holo.tif",0)
image = image
spectrum = np.fft.fftshift(np.fft.fft2(image))
intensity = 10*np.log(np.abs(spectrum))
mask = intensity.astype(bool)
img = intensity.astype(float)
graph = image.img_to_graph(img, mask=mask)
graph.data = np.exp(-graph.data/graph.data.std())
labels = spectral_clustering(graph, k=2, mode = 'arpack')
label_img = -np.ones(mask.shape)
label_im[mask] = labels
So I'm trying to use the "spectral clustering" function but I get this error:
AttributeError: 'numpy.ndarray' object has no attribute 'img_to_graph'
How can I do for converting my "intensity" numpy array into a correct img_to_graph attribute?
You are overwriting your imported image = sklearn.feature_extraction.image with image = cv2.imread("/home/facu/holo.tif",0), so the function img_to_graph will not be accessible anymore.
The solution is to rename one of them, e.g. with
raw_img = cv2.imread("/home/facu/holo.tif",0)
and adjusting the rest accordingly.

Categories