Histogram of my cam in real time - python

Im trying to show the histogram in real time from grayscale of my webcam, the problem is that histogram is not being update and my cam stop until i close histogram's window. How can i fix this? I want to show the grayscale img from my webcam and its histogram in same time, is possible do that?
import numpy as np
import cv2
from matplotlib import pyplot as plt
cap = cv2.VideoCapture(0)
while(True):
ret, frame = cap.read()
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
cv2.imshow('Janela', frame)
cv2.imshow('Outra', gray)
plt.hist(gray.ravel(), 256, [0, 256])
plt.show()
if (cv2.waitKey(1) & 0xFF == 27):
break
cap.release()
cv2.destroyAllWindows()

I have been working for a while in the same task. After some time, I have a piece of code that works very good. It displays the camera image in a window and a histogram in other. Since I'm interested in finding colors, I'm working with the "hue" channel of each frame.
# import the necessary packages
import cv2
import numpy as np
#Create window to display image
cv2.namedWindow('colorhist', cv2.WINDOW_AUTOSIZE)
#Set hist parameters
hist_height = 64
hist_width = 256
nbins = 32
bin_width = hist_width/nbins
camera_id = 0 # type fo webcam [0 built-in | 1 external]
cameraWidth = 320
cameraHeight = 240
if camera_id == 0:
cameraId = "PC webcam"
elif camera_id == 1:
cameraId = "External webcam"
camera = cv2.VideoCapture(camera_id)
# set camera image to 320 x 240 pixels
camera.set(3,cameraWidth)
camera.set(4,cameraHeight)
cameraInfo = "Image size (%d,%d)" % (camera.get(3),camera.get(4))
# initialize mask matrix
mask = np.zeros((cameraHeight,cameraWidth), np.uint8)
# draw a circle in mask matrix
cv2.circle(mask,(cameraWidth/2,cameraHeight/2), 50, 255, -1)
#Create an empty image for the histogram
h = np.zeros((hist_height,hist_width))
#Create array for the bins
bins = np.arange(nbins,dtype=np.int32).reshape(nbins,1)
while True:
# grab the current frame
(grabbed, frame) = camera.read()
if not grabbed:
"Camera could not be started."
break
hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
#Calculate and normalise the histogram
hist_hue = cv2.calcHist([hsv],[0],mask,[nbins],[0,256])
cv2.normalize(hist_hue,hist_hue,hist_height,cv2.NORM_MINMAX)
hist=np.int32(np.around(hist_hue))
pts = np.column_stack((bins,hist))
#Loop through each bin and plot the rectangle in white
for x,y in enumerate(hist):
cv2.rectangle(h,(x*bin_width,y),(x*bin_width + bin_width-1,hist_height),(255),-1)
#Flip upside down
h=np.flipud(h)
#Show the histogram
cv2.imshow('Color Histogram',h)
h = np.zeros((hist_height,hist_width))
frame = cv2.bitwise_and(frame,frame,mask = mask)
cv2.putText(frame, cameraInfo, (10, 20),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2)
cv2.imshow(cameraId, frame)
key = cv2.waitKey(1) & 0xFF
# if the `q` key is pressed, break from the loop
if key == ord("q"):
break
camera.release()
cv2.destroyAllWindows()
The code is based on the code from JohnLinux post (How do I plot a 32-Bin Histogram for a Grayscale Image in Python using OpenCV) and other lines of code come from what I have learnt from Adrian Rosenbrock's site https://www.pyimagesearch.com/.

I see there is very little feedback on this topic. Some solutions look overwhelmingly complex. My brother needed just a simple version of such programme for his studies, so I decided to write it as simple as it can be (11 lines of code - enjoy:))
import cv2 as cv
from matplotlib import pyplot as plt
vid = cv.VideoCapture(0, cv.CAP_DSHOW)
while True:
ret, img = vid.read()
cv.imshow("img", img)
plt.hist(img.ravel(), 256, [0, 256])
plt.draw()
plt.pause(0.1)
plt.clf()
cv.destroyAllWindows()

another solution for the picamera doing stream + histogram
from picamera import PiCamera
from picamera.array import PiRGBArray
import cv2
import matplotlib.pyplot as plt
camera = PiCamera()
camera.resolution = (640, 480)
camera.framerate = 40
rawCapture = PiRGBArray(camera, size=(640, 480))
for frame in camera.capture_continuous(rawCapture, format="bgr", use_video_port=True):
bgr_arr = frame.array
gray_arr = cv2.cvtColor(bgr_arr, cv2.COLOR_BGR2GRAY)
cv2.imshow("Preview", gray_arr)
key = cv2.waitKey(1) & 0xFF
rawCapture.truncate(0)
plt.hist(gray_arr.ravel(), 256, [0, 256], histtype='stepfilled')
plt.title('Grayscale histogram')
plt.xlabel('Grayscale value')
plt.ylabel('Pixel count')
plt.plot()
plt.pause(0.1)
plt.clf()
if key == ord("q"):
cv2.destroyAllWindows()
break

Related

How do I add an image overlay to my live video using cv2?

This is my code, I've looked at some tutorials but can't find what I'm looking for
I want to overlay the Frame.png image on my webcam. I tried to add the image directly but it didn't work either. If possible, Is there a way to add an image, not to overlay but to keep the image at a certain coordinate in the live webcam window
import cv2
import numpy as np
def detect_and_save():
alpha = 0.2
beta = 1-alpha
cap = cv2.VideoCapture(0)
sciframe = cv2.imread('Frame.png')
classifier = cv2.CascadeClassifier("haarcascade_frontalface_default.xml")
while True:
ret ,frame = cap.read()
overlay = frame.copy()
output = frame.copy()
gray = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
faces = classifier.detectMultiScale(gray,1.5,5)
cv2.putText(output, "HUD Test",(175, 50), cv2.FONT_HERSHEY_SIMPLEX, 2, (255, 50, 50), 3)
cv2
for face in faces:
x,y,w,h = face
cv2.rectangle(overlay,(x,y),(x+w,y+h),(255,200,0),-1)
cv2.rectangle(overlay,(x,y),(x+w,y+h),(255,0,0),1)
cv2.rectangle(overlay,(x,y-20),(x+w,y),(25,20,0),-1)
cv2.addWeighted(overlay,alpha,output,beta,0,output)
cv2.putText(output,"Human",(x+10,y-10),cv2.FONT_HERSHEY_SIMPLEX,
0.35, (0, 0, 255), 1)
if not ret:
continue
cv2.imshow("HUD",output)
key = cv2.waitKey(1)
if key == ord('q'):
break
elif key == ord('s'):
cv2.imwrite('./images/CID_{}.png'.format(time.strftime('%d%m%y_%H_%M_%S')),output)
cap.release()
cv2.destroyAllWindows()
if __name__ == "__main__":
import time
detect_and_save()
You can directly add one image on top of another one at any coordinate easily in opencv.
cap = cv2.VideoCapture(0)
im_height = 50 #define your top image size here
im_width = 50
im = cv2.resize(cv2.imread("Frame.png"), (im_width, im_height))
while (True):
ret, frame = cap.read()
frame[0:im_width, 0:im_height] = im #for top-left corner, 0:50 and 0:50 for my image; select your region here like 200:250
cv2.imshow("live camera", frame)
if cv2.waitKey(1) == ord("q"):
break
cap.release()
cv2.destroyAllWindows()

OpenCV Python - Draw circle at random position in webcam video feed

I have the following code:
import cv2
from random import randrange
cap = cv2.VideoCapture(0) #record webcam
while True:
ret, frame = cap.read() #get feed from webcam
h, w = frame.shape[:2] #height, width
randomWidth = randrange(30,w-30)
randomHeight = randrange(70,h-30)
coordinates = (randomWidth, randomHeight)
circle = cv2.circle(frame, coordinates, 30, (0,0,255), -1) #circle
cv2.imshow('webcam', frame) #show webcam
if cv2.waitKey(1) == ord('q'): #press 'q' to close
break
cap.release()
cv2.destroyAllWindows()
My goal is to have the circle displayed at a random position every time I run the program. However, with this current code, the circle is jumping all over the screen, being drawn at a random position with every frame. How can I modify this code so that the circle is drawn at a random width and height and stays in that position until I exit the program?
You are recalculating the coordinates in each iteration, which is why the circle keeps moving around. You want to only calculate coordinates once and then keep using that value. Here is one way to do so:
import cv2
from random import randrange
cap = cv2.VideoCapture(0) #record webcam
ret, frame = cap.read() #get feed from webcam
h, w = frame.shape[:2] #height, width
randomWidth = randrange(30, w-30)
randomHeight = randrange(70, h-30)
coordinates = (randomWidth, randomHeight)
while True:
ret, frame = cap.read() #get feed from webcam
circle = cv2.circle(frame, coordinates, 30, (0,0,255), -1) #circle
cv2.imshow('webcam', frame) #show webcam
if cv2.waitKey(1) == ord('q'): #press 'q' to close
break
cap.release()
cv2.destroyAllWindows()
The frame is fetched once before the loop, used to get random coordinates and then the loop continues to update the frame with the circle being at fixed coordinates.
In case your requirement may involve a changing frame.shape or there is some situation where coordinates may need to be recalculated in the loop, using a condition like below can be more flexible because coordinates is None can be replaced with different criteria:
import cv2
from random import randrange
cap = cv2.VideoCapture(0) #record webcam
coordinates = None
while True:
ret, frame = cap.read() #get feed from webcam
if coordinates is None:
h, w = frame.shape[:2] #height, width
randomWidth = randrange(30, w-30)
randomHeight = randrange(70, h-30)
coordinates = (randomWidth, randomHeight)
circle = cv2.circle(frame, coordinates, 30, (0,0,255), -1) #circle
cv2.imshow('webcam', frame) #show webcam
if cv2.waitKey(1) == ord('q'): #press 'q' to close
break
cap.release()
cv2.destroyAllWindows()

How to Save the trackbar values after closing the python code using Opencv?

I am using opencv to detect the color of objects by using HSV trackbars values and I want my python code to save the latest changes I would make to the trackbars in opencv , when I start the code again, the trackbars will have the last values? below is my code
import numpy as np
import cv2
# open the camera
cap = cv2.VideoCapture(0)
def nothing(x):
pass
cv2.namedWindow('result')
# Starting with 100's to prevent error while masking
h,s,v = 100,100,100
# Creating track bar
cv2.createTrackbar('h', 'result',0,179,nothing)
cv2.createTrackbar('s', 'result',0,255,nothing)
cv2.createTrackbar('v', 'result',0,255,nothing)
while True:
#read the image from the camera
ret, frame = cap.read()
#You will need this later
frame = cv2.cvtColor(frame, 35)
#converting to HSV
hsv = cv2.cvtColor(frame,cv2.COLOR_BGR2HSV)
# get info from track bar and appy to result
h = cv2.getTrackbarPos('h','result')
s = cv2.getTrackbarPos('s','result')
v = cv2.getTrackbarPos('v','result')
# Normal masking algorithm
lower_blue = np.array([h,s,v])
upper_blue = np.array([180,255,255])
mask = cv2.inRange(hsv,lower_blue, upper_blue)
result = cv2.bitwise_and(frame,frame,mask = mask)
cv2.imshow('result',result)
#find center
cnts=cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)[-2]
center=None
if len(cnts)>0:
c=max(cnts, key=cv2.contourArea)
((x,y),radius)=cv2.minEnclosingCircle(c)
M=cv2.moments(c)
center=(int(M["m10"] / M["m00"]), int(M["m01"] / M["m00"]))
if radius>10:
#cv2.circle(frame, (int(x),int(y)), int(radius), 2)
cv2.circle(frame, center,5,(0,0,255),-1)
# color detection limits
lB = 5
lG = 50
lR = 50
hB = 15
hG = 255
hR = 255
lowerLimits = np.array([lB, lG, lR])
upperLimits = np.array([hB, hG, hR])
# Our operations on the frame come here
thresholded = cv2.inRange(frame, lowerLimits, upperLimits)
outimage = cv2.bitwise_and(frame, frame, mask = thresholded)
cv2.imshow('original', frame)
# Display the resulting frame
cv2.imshow('processed',outimage)
# Quit the program when Q is pressed
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# When everything done, release the capture
print 'closing program'
cap.release()
cv2.destroyAllWindows()
One option is to write the values to a text file somewhere, then when the program starts, read the file and parse the values written in the file.
See: How could I save data after closing my program?

OpenCV - Coloring a specific area during video capture?

Here is my code:
import cv2
import numpy as np
cap = cv2.VideoCapture(1)
fourcc = cv2.VideoWriter_fourcc('M','J','P','G')
framesize = (640,480)
out = cv2.VideoWriter('dump.avi',fourcc,60.0,framesize)
font = cv2.FONT_HERSHEY_SIMPLEX
while True:
ret, frame = cap.read()
gray = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
cv2.imshow('frame',frame)
cv2.rectangle(gray, (0,0),(640,480),(255,255,255),3)
cv2.putText(gray, "gray", (0,130),font, 5,(255,255,255),2, cv2.LINE_AA)
cv2.imshow('fr',gray)
Here I am trying to color a specific square area on the live image feed
#gray[100:105,110:115] = [255,255,255]
io = gray[37:111,107:194]
Here I am cloning an are into another
gray[200:200,270:283] = io
out.write(frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
out.release()
cv2.destroyAllWindows()
How can I color a specific area? As my attempt is not working.

Finding circles in a live video feed using python 2.7.11and opencv 3.0.0

I need help finding circles in a live video feed from my webcam. I just need feedback from python that a circle has or has not been detected. Also what is the best method for finding the size of the circle in pixels for better detection. My code so far
import cv2
import numpy as np
import sys
cap = cv2.VideoCapture(0)
while(True):
ret, frame = cap.read()
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
gray = cv2.medianBlur(gray,5)
cimg = frame.copy()
circles = cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, 1, 10, np.array([]), 200, 100, 100, 200)
if circles == 1:
print('Circle true')
else:
print('No circle')
cv2.imshow('video',gray)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
There it is !
import cv2
import numpy as np
import sys
cap = cv2.VideoCapture(0)
while(True):
gray = cv2.medianBlur(cv2.cvtColor(cap.read()[1], cv2.COLOR_BGR2GRAY),5)
cirles=cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, 1, 10)# ret=[[Xpos,Ypos,Radius],...]
if cirles!=None:print "Circle There !"
cv2.imshow('video',gray)
if cv2.waitKey(1)==27:# esc Key
break
cap.release()
cv2.destroyAllWindows()

Categories

Resources