Palette method using numpy - python

I am trying to apply the numpy palette method to an opencv processed video (references: this question and this tutorial ). I aim at replacing all frame pixels of a certain color range by another. The code below is an example that replaces black with green. Unfotunately, my code raises an error on line:
image[np.where((image==[0,0,0]).all(axis=2))]=green
the error: exceptions.ValueError:axis(=2) out of bounds
I am running python 2.7 with PyScripter, and I find it odd because the code did work before, and I did not make any major modification to it. Can someone please help me? I am quite stuck on this one...
My code:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
##IMPORTS
import cv2.cv as cv
import numpy as np
import time
##VARIABLES
#colors
green=[0,255,0]
##MAIN
#video file input
frames = raw_input('Please input video file:')
if not frames:
print "This program requires a file as input!"
sys.exit(1)
#create window
cv.NamedWindow("image", 1)
#File capture
vidFile = cv.CaptureFromFile(frames)
nFrames = int( cv.GetCaptureProperty( vidFile, cv.CV_CAP_PROP_FRAME_COUNT ) )
fps = cv.GetCaptureProperty( vidFile, cv.CV_CAP_PROP_FPS )
waitPerFrameInMillisec = int( 1/fps * 1000/1 )
#time adjustment, frame capture
for f in xrange( nFrames ):
frame = cv.QueryFrame( vidFile )
# create the images we need
image = cv.CreateImage (cv.GetSize (frame), 8, 3)
# copy the frame, so we can draw on it
if not frame:
break
else:
cv.Copy (frame, image)
#get pixel HSV colors
rows,cols=cv.GetSize(frame)
image=np.asarray(image)
image[np.where((image==[0,0,0]).all(axis=2))]=green
image=cv.fromarray(image)
#show the image
cv.ShowImage("image", image)
#quit command ESC
if cv.WaitKey(waitPerFrameInMillisec)==27:
break
else:
cv.WaitKey(waitPerFrameInMillisec) % 0x100

I solved it. In fact, the answer was not a modification of the line raising the exception, but rather on a modification of the arguments that were passed to this line. Indeed, it seems that the '[:,:]' arguments are required in opencv when converting cvMat to Numpy and back.
Here is the corrected code:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
##IMPORTS
import cv2.cv as cv
import numpy as np
##VARIABLES
#colors
green=[0,255,0]
##MAIN
#start video stream analysis
frames = raw_input('Please enter video file:')
if not frames:
print "This program requires a file as input!"
sys.exit(1)
# first, create the necessary windows
cv.NamedWindow ('image', cv.CV_WINDOW_AUTOSIZE)
#File capture
vidFile = cv.CaptureFromFile(frames)
nFrames = int( cv.GetCaptureProperty( vidFile, cv.CV_CAP_PROP_FRAME_COUNT ) )
fps = cv.GetCaptureProperty( vidFile, cv.CV_CAP_PROP_FPS )
waitPerFrameInMillisec = int( 1/fps * 1000/1 )
for f in xrange( nFrames ):
#time adjustment, frame capture
sec = f/fps
frame = cv.QueryFrame( vidFile )
# create the images we need
image = cv.CreateImage (cv.GetSize (frame), 8, 3)
# copy the frame, so we can draw on it
if not frame:
break
else:
cv.Copy (frame, image)
#Replace pixel colors
rows,cols=cv.GetSize(frame)
image=np.asarray(image[:,:])
image[np.where((image==[0,0,0]).all(axis=2))]=green
image=cv.fromarray(image[:,:])
#show the image
cv.ShowImage("image", image)
#quit command ESC
if cv.WaitKey(waitPerFrameInMillisec)==27:
break
else:
cv.WaitKey(waitPerFrameInMillisec) % 0x100
cv.DestroyAllWindows()

Related

accident detection project using webcam

I am getting an error in the code below. I want to take input from the webcam and if any accident occurs then it will shows that accident occurs. But with the code below I am not even getting camera video feed. It shows the following error:
AttributeError: 'module' object has no attribute 'CV_WINDOW_AUTOSIZE'
If I change it to cv2.WINDOW_NORMAL then it shows this error:
C:\build\master_winpack-bindings-win64-vc14-static\opencv\modules\imgproc\src\color.cpp:9748: error: (-215) scn == 3 || scn == 4 in function cv::cvtColor
Sometimes it turns on my laptop camera LED, and I want take video from the webcam.
#Import necessary packages
import numpy as np
import cv2
import math, operator
#Function to find difference in frames
def diffImg(t0, t1, t2):
d1 = cv2.absdiff(t2, t1)
d2 = cv2.absdiff(t1, t0)
return cv2.bitwise_and(d1, d2)
j=1
#Import video from webcam
cam = cv2.VideoCapture(0)
#Creating window to display
winName = "Accident Detector"
cv2.namedWindow(winName, cv2.CV_WINDOW_AUTOSIZE)
#Reading frames at multiple instances from webcam to different variables
t_minus = cv2.cvtColor(cam.read()[1], cv2.COLOR_RGB2GRAY)
t = cv2.cvtColor(cam.read()[1], cv2.COLOR_RGB2GRAY)
t_plus = cv2.cvtColor(cam.read()[1], cv2.COLOR_RGB2GRAY)
while True:
#Display video out through the window we created
cv2.imshow( winName, diffImg(t_minus, t, t_plus) )
#Calling function diffImg() and assign the return value to 'p'
p=diffImg(t_minus, t, t_plus)
#Writing 'p' to a directory
cv2.imwrite("D:\photos\shot.jpg",p)
#From Python Image Library(PIL) import Image class
from PIL import Image
#Open image from the directories and returns it's histogram's
h1 = Image.open("D:\motionpic\shot"+str(j)+".jpg").histogram()
h2 = Image.open("D:\photos\shot.jpg").histogram()
j=j+1
#Finding rms value of the two images opened before
rms = math.sqrt(reduce(operator.add,map(lambda a,b: (a-b)**2, h1, h2))/len(h1))
print int(rms)
#If the RMS value of the images are under our limit
if (rms<250):
#Then there is a similarity between images. i.e., Scene similar to an accident is found
print "accident\a"
#Updates the frames
t_minus = t
t = t_plus
t_plus = cv2.cvtColor(cam.read()[1], cv2.COLOR_RGB2GRAY)
#Destroys the window after key press
key = cv2.waitKey(10)
if key == 27:
cv2.destroyWindow(winName)
break
The correct syntax to create a new window is
cv2.namedWindow(winName, cv2.WINDOW_AUTOSIZE)
Also the camera frames should be read under the while loop.

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 wrong multiple output

I have a func that retrieve information from program. It point the mouse grab an image, resize it, then get recognized with tesseract and add to ValueIndex.
from PIL import Image
import pytesseract
import pyscreenshot as ImageGrab
from pynput.mouse import Button, Controller
import re
def GetValues(): #Read matrix of digit from
pytesseract.pytesseract.tesseract_cmd ='C:\\Program Files (x86)\\Tesseract-OCR\\tesseract'
mouse = Controller()
Mul=2
ValueIndex=[0 for i in range(0,170)] # Results
y1=163
if __name__ == "__main__":
for j in range(0,1):# get 1 line for example
y1=y1+67
x1=1350
for i in range(0,13):
x1=x1+67
mouse.position = (x1, y1)
mouse.press(Button.left)
mouse.release(Button.left)
im=ImageGrab.grab(bbox=(1485, 1112,1680, 1177))
x,y = im.size
x=x*Mul
y=y*Mul
size=x,y
im_resized = im.resize(size, Image.ANTIALIAS) # resize for tesseract
im_resized.save('test%s.png' % i)
data = pytesseract.image_to_string(im_resized)
q=''.join(re.findall('\d',data)) # gt digits from str
if (len(q)==4):
q=indexq[:2]+'.'+q[2:]
if len(q)==3:
q=q[:1]+'.'+q[1:]
GetInd=j*13+i+1
ValueIndex[GetInd]=float(q)
print(i,' ',data,' ',ValueIndex[GetInd]) # print to see the progress
return(ValueIndex)
GetValues() #When i comment it, print only 1 time
print('Why so many times?:)')
It work properly, but when i add print in body of prorgam it output multiple times. It's not in func loop, whats wrong?
Why so many times?:)
0 +9.76% 9.76
Why so many times?:)
1 +619% 6.19
Why so many times?:)
2 +5.36% 5.36
and so on

OpenCV2 - Narrow Rectangles found using SimpleBlobDetector, but can't extract the angle

I'm trying to get the angle of the middle line in a domino. SimpleBlobDetector can find it, but it gives me an angle value of -1.
Does anyone know why that can be? and how can i fix that still using SimpleBlobDetector? and if SimpleBlobDetector is not an option, what else can i do to find the center and angle of these lines?
import numpy as np
import cv2
import os
import time
#from matplotlib import pyplot as plt
def main():
capWebcam = cv2.VideoCapture(0) # declare a VideoCapture object and associate to webcam, 0 => use 1st webcam
params = cv2.SimpleBlobDetector_Params()
params.filterByCircularity = True
params.minCircularity = 0.73
params2 = cv2.SimpleBlobDetector_Params()
params2.filterByInertia = True
params2.maxInertiaRatio = 0.3
# show original resolution
print "default resolution = " + str(capWebcam.get(cv2.CAP_PROP_FRAME_WIDTH)) + "x" + str(capWebcam.get(cv2.CAP_PROP_FRAME_HEIGHT))
capWebcam.set(cv2.CAP_PROP_FRAME_WIDTH, 320.0) # change resolution to 320x240 for faster processing
capWebcam.set(cv2.CAP_PROP_FRAME_HEIGHT, 240.0)
capWebcam.set(cv2.CAP_PROP_FPS, 1)
# show updated resolution
print "updated resolution = " + str(capWebcam.get(cv2.CAP_PROP_FRAME_WIDTH)) + "x" + str(capWebcam.get(cv2.CAP_PROP_FRAME_HEIGHT))
if capWebcam.isOpened() == False: # check if VideoCapture object was associated to webcam successfully
print "error: capWebcam not accessed successfully\n\n" # if not, print error message to std out
os.system("pause") # pause until user presses a key so user can see error message
return # and exit function (which exits program)
# end if
while cv2.waitKey(1) != 27 and capWebcam.isOpened(): # until the Esc key is pressed or webcam connection is lost
blnFrameReadSuccessfully, img = capWebcam.read() # read next frame
if not blnFrameReadSuccessfully or img is None: # if frame was not read successfully
print "error: frame not read from webcam\n" # print error message to std out
os.system("pause") # pause until user presses a key so user can see error message
break # exit while loop (which exits program)
det = cv2.SimpleBlobDetector_create(params)
det2 = cv2.SimpleBlobDetector_create(params2)
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
time.sleep(0.1)
keypts = det.detect(gray)
time.sleep(0.1)
keypts2 = det2.detect(gray)
print len(keypts)
print len(keypts2)
for l in keypts2:
print l.pt
print l.angle
time.sleep(0.3)
imgwk = cv2.drawKeypoints(gray, keypts, img,color= (200,0,139),flags=2)
time.sleep(0.1)
imgwk2 = cv2.drawKeypoints(img, keypts2, gray,color= (200,0,139),flags=2)
cv2.namedWindow("img", cv2.WINDOW_AUTOSIZE) # or use WINDOW_NORMAL to allow window resizing
cv2.imshow("img", img)
# hold windows open until user presses a key
cv2.destroyAllWindows()
return
###################################################################################################
if __name__ == "__main__":
main()
I'm not sure if SimpleBlob detector is the best for this, but have you looked at
Detect centre and angle of rectangles in an image using Opencv
It seems quite similar to you question, and seems to do very well at identifying the angle of the rectangles

OpenCV - Save video segments based on certion condition

Aim : Detect the motion and save only the motion periods in files with names of the starting time.
Now I met the issue about how to save the video to the files with video starting time.
What I tested :
I tested my program part by part. It seems that each part works well except the saving part.
Running status: No error. But in the saving folder, there is no video. If I use a static saving path instead, the video will be saved successfully, but the video will be override by the next video. My codes are below:
import cv2
import numpy as np
import time
cap = cv2.VideoCapture( 0 )
bgst = cv2.createBackgroundSubtractorMOG2()
fourcc=cv2.VideoWriter_fourcc(*'DIVX')
size = (int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)), int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)))
n = "start_time"
while True:
ret, frame = cap.read()
dst = bgst.apply(frame)
dst = np.array(dst, np.int8)
if np.count_nonzero(dst)>3000: # use this value to adjust the "Sensitivity“
print('something is moving %s' %(time.ctime()))
path = r'E:\OpenCV\Motion_Detection\%s.avi' %n
out = cv2.VideoWriter( path, fourcc, 50, size )
out.write(frame)
key = cv2.waitKey(3)
if key == 32:
break
else:
out.release()
n = time.ctime()
print("No motion Detected %s" %n)
What I meant is:
import cv2
import numpy as np
import time
cap = cv2.VideoCapture( 0 )
bgst = cv2.createBackgroundSubtractorMOG2()
fourcc=cv2.VideoWriter_fourcc(*'DIVX')
size = (int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)),int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)))
path = r'E:\OpenCV\Motion_Detection\%s.avi' %(time.ctime())
out = cv2.VideoWriter( path, fourcc, 16, size )
while True:
ret, frame = cap.read()
dst = bgst.apply(frame)
dst = np.array(dst, np.int8)
for i in range(number of frames in the video):
if np.count_nonzero(dst)<3000: # use this value to adjust the "Sensitivity“
print("No Motion Detected")
out.release()
else:
print('something is moving %s' %(time.ctime()))
#label each frame you want to output here
out.write(frame(i))
key = cv2.waitKey(1)
if key == 32:
break
cap.release()
cv2.destroyAllWindows()
If you see the code there will be a for loop, within which the process of saving is done.
I do not know the exact syntax involving for loop with frames, but I hope you have the gist of it. You have to find the number of frames present in the video and set that as the range in the for loop.
Each frame gets saved uniquely (see the else condition.) As I said I do not know the syntax. Please refer and follow this procedure.
Cheers!

Categories

Resources