How to get RGB values from a video? - python

I want to get the RGB values of a video and put it in a 2D array with frames (frame,rgb value) and save it in a file.
I only found a way to get it on image pixles and don't know how to save the array in a file.
from PIL import Image
im = Image.open("D:\swim\Frames1\Frames1.png")
pix=im.load()
width, height = im.size
pixels = [pix[i, j] for i in range(width) for j in range(height)]
print (pixels)
in conclusion: I want to load a video and convert it to an array consisting of frames,RGB is that possible?
I have tried
from numpy import asarray
from numpy import savetxt
import cv2
cap = cv2.VideoCapture('D:\swim\swim99.mp4')
rgb_list = []
while True:
ret, frame = cap.read()
if not ret:
break
rgb_frame_i = frame.reshape(-1, 3).tolist()
rgb_list.extend(rgb_frame_i)
print(rgb_frame_i)
but it didn't print anything and I don't know how to save it in a file.

Things you should know:
Step 1 - Convert your videos into Frames
import numpy as np
import cv2 as cv
cap = cv.VideoCapture(0)
if not cap.isOpened():
print("Cannot open camera")
exit()
while True:
# Capture frame-by-frame
ret, frame = cap.read()
-------------------------------------------------------------> step 2 - split
# if frame is read correctly ret is True
if not ret:
print("Can't receive frame (stream end?). Exiting ...")
break
# Our operations on the frame come here
gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)
# Display the resulting frame
cv.imshow('frame', gray)
if cv.waitKey(1) == ord('q'):
break
# When everything done, release the capture
cap.release()
cv.destroyAllWindows()
Step 2 - Split your frames into B,G,R
b,g,r = cv2.split(frame)
Step 3 - Save independent frames and convert to a video.

Related

How to insert a smaller image in an opencv Videocapture frame?

So, I have this code, I can easily add a text or any shape in opencv frame.
But inserting an image on a frame is a very difficult one.
I want to insert a smaller image on a Videocapture frame, let say the image to be inserted is a 50x50 pixel.
Any idea on this?
import cv2
webcam = cv2.VideoCapture(0)
insertImage = "sample.jpg" # size 50x50
while True:
rval = False
while(not rval):
(rval, frame) = webcam.read()
if(not rval):
print("Failed to open webcam. Trying again...")
cv2.putText(frame, " image here ", (0,70),cv2.FONT_HERSHEY_SIMPLEX, 0.6, (255,0,0), 2)
cv2.imshow('with image', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
webcam.release()
cv2.destroyAllWindows()
OpenCv images are numpy arrays. As far as I know, OpenCv does not provide functions with which you can get what you want. The result can be achieved by manipulating arrays.
import cv2
import numpy as np
if __name__ == '__main__':
bigImage = cv2.imread("image1.png") #I don't have a webcam connected, so it's your frame
smallImage = cv2.imread("image2.png") #50x50 for you
height, width, channels = smallImage.shape
offset = np.array((40, 50)) #top-left point from which to insert the smallest image. height first, from the top of the window
bigImage[offset[0]:offset[0] + height, offset[1]:offset[1] + width] = smallImage
cv2.imshow("test", bigImage)
cv2.waitKey(0)
Input
bigImage = big gray rectangle. It is your frame
smallImage = small green rectangle. It is your 50x50 image
Output

Replacing 3D submatrix in Numpy and OpenCV2

Replace sub part of matrix by another small matrix in numpy generally seems to work for my purposes but I'm running into something I can't reconcile. Consider the following code, that creates two 3D matrices the shape of OpenCV2 webcam input, (in my case (480, 640, 3)), one of all 1s (frame) and one of random floats (rgb_noise_mask), replaces a specified submatrix in frame with the same submatrix of rgb_noise_mask, and displays it to the screen. This code works as intended, displaying a block of RGB-based static on a field of white.
import numpy as np
import cv2
cap = cv2.VideoCapture(0)
ret, frame = cap.read()
frame = np.ones(frame.shape)
rgb_noise_mask = np.random.random(size=frame.shape)
while True:
boxes = [[300,300,30,30]]
for box in boxes:
x, y, width, height = box
frame[y:y2, x:x2] = rgb_noise_mask[y:y2, x:x2]
cv2.imshow("frame", frame)
if cv2.waitKey(1) & 0xFF == ord("q"):
break
cap.release()
cv2.destroyAllWindows()
Now take off the training wheels and use the actual webcam input instead of faking it. That same box now appears as uniform black instead of the expected colors:
import numpy as np
import cv2
cap = cv2.VideoCapture(0)
ret, frame = cap.read()
rgb_noise_mask = np.random.random(size=frame.shape)
while True:
ret, frame = cap.read()
boxes = [[300,300,30,30]]
for box in boxes:
x, y, width, height = box
frame[y:y2, x:x2] = rgb_noise_mask[y:y2, x:x2]
cv2.imshow("frame", frame)
if cv2.waitKey(1) & 0xFF == ord("q"):
break
cap.release()
cv2.destroyAllWindows()
Why is this, and how can I get around it? Further adding to my confusion is that if I replace frame[y:y2, x:x2] = rgb_noise_mask[y:y2, x:x2] with frame[y:y2, x:x2] = frame[y:y2, x:x2][::-1] in the second code sample it behaves as expected and displays the live output with that square mirrored.
The issue here is that ret, frame = cap.read() returns frame as a numpy array with dtype=np.uint8, while rgb_noise_mask is float between 0,1, so all 0 when converted to uint8.
A simple fix is to generate noise as integers with randint:
rgb_noise_mask = np.random.randint(0,256, size=frame.shape, dtype=np.uint8)

Controlling Contrast and Brightness of Video Stream in OpenCV and Python

I’m using OpenCV3 and Python 3.7 to capture a live video stream from my webcam and I want to control the brightness and contrast. I cannot control the camera settings using OpenCV's cap.set(cv2.CAP_PROP_BRIGHTNESS, float) and cap.set(cv2.CAP_PROP_BRIGHTNESS, int) commands so I want to apply the contrast and brightness after each frame is read. The Numpy array of each captured image is (480, 640, 3). The following code properly displays the video stream without any attempt to change the brightness or contrast.
import numpy as np
import cv2
cap = cv2.VideoCapture(0)
while(True):
# Capture frame-by-frame
ret, frame = cap.read()
cv2.imshow('frame',frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# When everything done, release the capture
cap.release()
cv2.destroyAllWindows()
I get a washed-out video stream when I use Numpy’s clip() method to control the contrast and brightness, even when I set contrast = 1.0 (no change to contrast) and brightness = 0 (no change to brightness). Here is my attempt to control contrast and brightness.
import numpy as np
import cv2
cap = cv2.VideoCapture(0)
while(True):
# Capture frame-by-frame
ret, frame = cap.read()
contrast = 1.0
brightness = 0
frame = np.clip(contrast * frame + brightness, 0, 255)
cv2.imshow('frame',frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# When everything done, release the capture
cap.release()
cv2.destroyAllWindows()
How can I control the contrast and brightness of a video stream using OpenCV?
I found the solution using the numpy.clip() method and #fmw42 provided a solution using the cv2.normalize() method. I like the cv2.normalize() solution slightly better because it normalizes the pixel values to 0-255 rather than clip them at 0 or 255. Both solutions are provided here.
The cv2.normalize() solution:
Brightness - shift the alpha and beta values the same amount. Alpha
can be negative and beta can be higher than 255. (If alpha >= 255,
then the picture is white and if beta <= 0, then the picure is black.
Contrast - Widen or shorten the gap between alpha and beta.
Here is the code:
import numpy as np
import cv2
cap = cv2.VideoCapture(0)
while(True):
# Capture frame-by-frame
ret, frame = cap.read()
cv2.normalize(frame, frame, 0, 255, cv2.NORM_MINMAX)
cv2.imshow('frame',frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# When everything done, release the capture
cap.release()
cv2.destroyAllWindows()
The numpy.clip() solution:
This helped me solve the problem: How to fast change image brightness with python + OpenCV?. I need to:
Convert Red-Green Blue (RGB) to Hue-Saturation-Value (HSV) first
(“Value” is the same as “Brightness”)
“Slice” the Numpy array to the Value portion of the Numpy array and adjust brightness and contrast on that slice
Convert back from HSV to RGB.
Here is the working solution. Vary the contrast and brightness values. numpy.clip() ensures that all the pixel values remain between 0 and 255 in each on the channels (R, G, and B).
import numpy as np
import cv2
cap = cv2.VideoCapture(0)
while(True):
# Capture frame-by-frame
ret, frame = cap.read()
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
contrast = 1.25
brightness = 50
frame[:,:,2] = np.clip(contrast * frame[:,:,2] + brightness, 0, 255)
frame = cv2.cvtColor(frame, cv2.COLOR_HSV2BGR)
cv2.imshow('frame',frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# When everything done, release the capture
cap.release()
cv2.destroyAllWindows()
import cv2 as cv
cap = cv.VideoCapture(0)
while True:
# Capture frame-by-frame
ret, frame = cap.read()
# normalize the frame
frame = cv.normalize(
frame, None, alpha=0, beta=255, norm_type=cv.NORM_MINMAX, dtype=cv.CV_8UC1
)
# Display the resulting frame
cv.imshow("frame", frame)
# press q to quit
if cv.waitKey(1) & 0xFF == ord("q"):
break

How do I find an image similar to the input image from a directory?

I have a python program which will detect images from webcam. Now, I want to compare the image recognized by the webcam with the images in my directory and check if the exact similar image is already existing or not.
I have tried using this recognition algorithm but it does not work. The program always outputs single image no matter how different the input image is.
The input image(the image scanned by the webcam) is little blurry like this while the image in the data set looks like this
I need an algorithm which can recognize these images with more accuracy.
Here i write a small script for you, hope that it could solve your problem
import cv2
import os
import numpy as np
from matplotlib import pyplot as plt
from PIL import Image
def read_img_from_dir(directory, query_shape):
# query_shape is a tuple which contain the size (width, height) of query image
# directory is your dir contain image you wanna find
name_image = []
shape = query
first = True
for pics in os.listdir(directory):
name_image.append(pics)
image = Image.open(pics)
image = image.resize(shape)
image = np.array(image)
image = np.reshape(image,(1,-1))
if first:
img_array = np.copy(image)
first = False
else:
img_array = np.concatenate((img,array,image),axis=0)
return name_image, img_array
def find_by_knn(img, list_name, list_array):
# image_query is path of your picture you wanna find
# list_name and list_array is result of above function
img = np.reshape(img,(1,-1))
num_pics = list_array.shape[0]
dists = np.zeros((num_pics,1))
dists = list(np.sqrt(np.sum((list_array-img)**2,axis = 1)))
idx = dists.index(max(dists))
return list_name[idx]
img = cv2.imread(image_query)
shape = img.shape[:2]
name_image, img_array = read_img_from_dir(directory,shape)
result = find_by_knn(img, name_image, img_array)
print(result)
If you wanna know more about KNN, take a look at this link: http://cs231n.github.io/classification/#nn
IMAGE SEARCH by using python openCV.
LINK FOR open CV
opencv_python‑4.1.0+contrib‑cp35‑cp35m‑win_amd64.whl
download the import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('watch.jpg',cv2.IMREAD_GRAYSCALE)
cv2.imshow('image',img)
cv2.waitKey(0)
cv2.destroyAllWindows()
pip install numpy
pip install matplotlib
Matplotlib is used for displaying frames from video or images.
Numpy is used for all things "numbers and Python."
We are mainly making use of Numpy's array functionality.
import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('watch.jpg',cv2.IMREAD_GRAYSCALE)
cv2.imshow('image',img)
cv2.waitKey(0)
cv2.destroyAllWindows()
Firstly we are going to import few things
Next, we define img to be cv2.read(image file, parms).
The default is going to be IMREAD_COLOR, which is color without any alpha channel.
For the second parameter, you can use -1, 0, or 1. Color is 1, gray scale is 0, and the unchanged is -1. Thus, for gray scale, one could do img = cv2.imread('watch.jpg', 0)
Once loaded, we use cv2.imshow(title,image) to show the image. From here,
we use the cv2.waitKey(0) to wait until any key is pressed. Once that's done,
we use cv2.destroyAllWindows() to close everything.
Loading Video Source Open CV Python
with video and webcams.
handling frames from a video is identical to handling for images.
code--
import numpy as np
import cv2
cap = cv2.VideoCapture(0)
while(True):
ret, frame = cap.read()
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
cv2.imshow('frame',gray)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
we import numpy and cv2 Next, we cay cap = cv2.VideoCapture(0).
while(True):
ret, frame = cap.read()
we have ret and frame being defined as the cap.read().
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
*we define a new variable, gray, as the frame, converted to gray.
note**
*OpenCV reads colors as BGR (Blue Green Red),
where most computer applications read as RGB (Red Green Blue).
cv2.imshow('frame',gray)
Here, we're showing the converted-to-gray feed.
if cv2.waitKey(1) & 0xFF == ord('q'):
break
if key is a q, we will exit the while loop with a break, which then runs:
cap.release()
cv2.destroyAllWindows()
This releases the webcam, then closes all of the imshow() windows.
if you want to save the recording and then process it by using,
import numpy as np
import cv2
cap = cv2.VideoCapture(1)
fourcc = cv2.VideoWriter_fourcc(*'XVID')
out = cv2.VideoWriter('output.avi',fourcc, 20.0, (640,480))
while(True):
ret, frame = cap.read()
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
out.write(frame)
cv2.imshow('frame',gray)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
out.release()
cv2.destroyAllWindows()

How to get previous frame of a video in opencv python

I want to detect obstacles from a video based on their increasing size.To do that first I applied SIFT on gray image to get feature points of current frame. Next to compare the feature points of current frame with the previous frame I want to apply Brute-Force algorithm. For that I want to get feature points in previous frame. How can I access previous frame in opencv python ? and how to avoid accessing previous frame when the current frame is the first frame of the video?
below is the code written in python to get feature points of current frame.
import cv2
import numpy as np
cap = cv2.VideoCapture('video3.mov')
while(cap.isOpened()):
ret, frame = cap.read()
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
#detect key feature points
sift = cv2.xfeatures2d.SIFT_create()
kp, des = sift.detectAndCompute(gray, None)
#draw key points detected
img=cv2.drawKeypoints(gray,kp,gray,flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
cv2.imshow("grayframe",img)
if cv2.waitKey(100) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
You could also get/set the zero-based frame index (CAP_PROP_POS_FRAMES), which might be useful if you wanted flexibility to step back through more than one frame, compare to a specific frame, etc. Note though that this would reset the position for the next read(), so if you really only ever want the previous frame, storing it in a variable per the other answers is probably better.
next_frame = cap.get(cv2.CAP_PROP_POS_FRAMES)
current_frame = next_frame - 1
previous_frame = current_frame - 1
if previous_frame >= 0:
cap.set(cv2.CAP_PROP_POS_FRAMES, previous_frame)
ret, frame = cap.read()
There is no specific function in OpenCV to access the previous frame. Your problem can be solved by calling cap.read() once before entering the while loop. Use a variable prev_frame to store the previous frame just before reading the new frame. Finally, as a good practice, you should verify that the frame was properly read, before doing computations on it. Your code could look something like:
import cv2
import numpy as np
cap = cv2.VideoCapture('video3.mov')
ret, frame = cap.read()
while(cap.isOpened()):
prev_frame=frame[:]
ret, frame = cap.read()
if ret:
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
#detect key feature points
sift = cv2.xfeatures2d.SIFT_create()
kp, des = sift.detectAndCompute(gray, None)
#some magic with prev_frame
#draw key points detected
img=cv2.drawKeypoints(gray,kp,gray, flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
cv2.imshow("grayframe",img)
else:
print('Could not read frame')
if cv2.waitKey(100) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
Simply save the current frame to be the previous frame in the next iteration. Use a list, if you need more than 1.
import cv2
import numpy as np
cap = cv2.VideoCapture('video3.mov')
previousFrame=None
while(cap.isOpened()):
ret, frame = cap.read()
if previousFrame is not None:
#use previous frame here
pass
#save current frame
previousFrame=frame
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
#detect key feature points
sift = cv2.xfeatures2d.SIFT_create()
kp, des = sift.detectAndCompute(gray, None)
#draw key points detected
img=cv2.drawKeypoints(gray,kp,gray,flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
cv2.imshow("grayframe",img)
if cv2.waitKey(100) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()

Categories

Resources