I am trying to overlay a translucent B&W image over a coloured image, but all the sample code I've found on this website hasn't worked so far ;-;
At this point, I'm just trying to implement the functionality of overlaying an image over another one, but it keeps reporting errors.
# import the opencv library
import cv2
import numpy as np
def canny(frame):
# Convert to graycsale
img_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
max_value = np.max(img_gray)
threshold_value = int(max_value * 0.75)
ret, thresh = cv2.threshold(img_gray, threshold_value, 255, cv2.THRESH_BINARY)
# extract alpha channel from foreground image as mask and make 3 channels
alpha = frame[:,:,3]
alpha = cv2.merge([alpha,alpha,alpha])
# extract bgr channels from foreground image
front = frame[:,:,0:3]
# blend the two images using the alpha channel as controlling mask
result = np.where(alpha==(0,0,0), thresh, front)
# Display Canny Edge Detection Image
cv2.imshow('Canny Edge Detection',result)
# define a video capture object
vid = cv2.VideoCapture("videoplayback.mp4")
while(True):
# Capture the video frame
# by frame
ret, frame = vid.read()
canny(frame)
# the 'q' button is set as the
# quitting button you may use any
# desired button of your choice
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# After the loop release the cap object
vid.release()
# Destroy all the windows
cv2.destroyAllWindows()```
As of right now, the error is ["Traceback (most recent call last):
File "edge.py", line 34, in <module>
canny(frame)
File "edge.py", line 13, in canny
alpha = frame[:,:,3]
IndexError: index 3 is out of bounds for axis 2 with size 3']
When I change it to 2. it reports ["Traceback (most recent call last):
File "edge.py", line 34, in <module>
canny(frame)
File "edge.py", line 20, in canny
result = np.where(alpha==(0,0,0), thresh, front)
File "<__array_function__ internals>", line 180, in where
ValueError: operands could not be broadcast together with shapes (360,480,3) (360,480) (360,480,3) "]
Please let me know how I can fix this, or if there is another way to write this code ;-;
Related
When I open multiple images from a folder and try to convert each into BGR2HSV, I receive this error:
Traceback (most recent call last):
File "create_gestures_manual.py", line 123, in
get_img(lab_path)
File "create_gestures_manual.py", line 114, in get_img
store_images(g_id, dirr)
File "create_gestures_manual.py", line 61, in store_images
imgHSV = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
cv2.error: OpenCV(4.5.2) /tmp/pip-req-build-wu1ri_rx/opencv/modules/imgproc/src/color.simd_helpers.hpp:92: error: (-2:Unspecified error) in function 'cv::impl::{anonymous}::CvtHelper<VScn, VDcn, VDepth, sizePolicy>::CvtHelper(cv::InputArray, cv::OutputArray, int) [with VScn = cv::impl::{anonymous}::Set<3, 4>; VDcn = cv::impl::{anonymous}::Set<3>; VDepth = cv::impl::{anonymous}::Set<0, 5>; cv::impl::{anonymous}::SizePolicy sizePolicy = cv::impl::::NONE; cv::InputArray = const cv::_InputArray&; cv::OutputArray = const cv::_OutputArray&]'
Invalid number of channels in input image:
'VScn::contains(scn)'
where
'scn' is 1
Below are snippet of my code:
while True:
framee = cv2.imread(dirr,0)
img = cv2.flip(framee, 1)
cv2.imshow('IMG',img)
imgHSV = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
What does this mean?. Please help me out. And how to solve this
The source of the error is that framee is a single channel grayscale image (and so is img which is created based on it). It is not a 3 channel color image, and therefore cannot be converted directly to hsv.
As you can see in this link: imread, the 2nd parameter flags determines the format of the read image.
In your code you use 0, which internally maps to IMREAD_GRAYSCALE. So even if your image file contains an rgb image, it will be converted to 1 channel grayscale.
Since the default for flags is IMREAD_COLOR, you can simply use:
framee = cv2.imread(dirr)
On a side note: even if you don't want this default, it's recommended to use the opencv enum values (e.g. cv2.IMREAD_GRAYSCALE) instead of an integer. Doing so you would never encounter this problem.
you read your image as grayscale image.
change this part:
framee = cv2.imread(dirr)
to have bgr image and then convert bgr to hsv.
I'm learning in an academic course python 3 and we currently study this PIL library.
in a certain task I need to take a couple of images and to run some tests on them, and one of the tests is to merge a gray image to an RGB image using Image.merge().
I have copied the part which is relevant to my problem here but I might be wrong and copied too little:
imag1= Image.open(im1_file)
imag2= Image.open(im2_file)
# convert the images to grayscale
img1 = imag1.convert('L')
img2 = imag2.convert('L')
# calculate the images histograms
mat1= img1.load()
mat2= img2.load()
hist1= img1.histogram()
hist2= img2.histogram()
# creat lists for bright pixels in the images
hist1count= hist1[128:]
hist2count= hist2[128:]
sum1= sum(hist1count)
sum2= sum(hist2count)
# calculate the mean brightness for each image in those bright pixels
mean1= sum1/len(hist1count)
mean2 =sum2/len(hist2count)
# compare images total number of bright pixels and assign the image
if sum1 > sum2:
mat_saved= mat1
img_saved= img1
elif sum2 > sum1:
mat_saved= mat2
img_saved= img2
# and the mean brightness of the image with the larger amount of bright pixels to variables for later use
if mean1 > mean2:
rmean_saved= mean1
elif mean2> mean1:
rmean_saved= mean2
else:
r_mean_saved = Image.new('L', (w,h), 0)
# creat image for the new red channel in the output image
new_img = img_saved.copy()
w, h=new_img.size
new_mat = new_img.load()
# creat a red rectangle border to the selected output image
for x in range(w):
for y in range(h):
new_mat[x,0]= rmean_saved
new_mat[x, h-1]= rmean_saved
new_mat[0, y]= rmean_saved
new_mat[w-1, y]= rmean_saved
# merge the red channel image with blue and green channel images to creat the output image
img_mixed= Image.merge("RGB", (new_mat ,mat_saved , mat_saved))
It gives me back an error which says:
Traceback (most recent call last):
File "./Root/src/main.py", line 103, in c,selected_image,marked_img = compare_and_mark_images(im1_file,im2_file)
File "./Root/src/main.py", line 89, in compare_and_mark_images img_mixed= Image.merge("RGB", (new_mat ,mat_saved , mat_saved))
File "/usr/lib/python3/dist-packages/PIL/Image.py", line 2118, in merge if im.mode != getmodetype(mode):
AttributeError: 'PixelAccess' object has no attribute 'mode
Note: I think the code works fine from small tests I've done during writing, the problem starts in the last line, the merge() function.
I'm relatively new to scripting. (I know quite a bit but I also don't know quite a bit.)
I'm trying to have a simple script use OpenCV-Python to subtract two frames from a webcam and draw a bounding box around the changed pixels. The issue is that when I try to define the boundingRect (x,y,w,h = cv2.boundingRect(contours)) it gives the error:
Message=OpenCV(4.5.3) :-1: error: (-5:Bad argument) in function 'boundingRect'
> Overload resolution failed:
> - array is not a numpy array, neither a scalar
> - Expected Ptr<cv::UMat> for argument 'array'
I've been searching around for quite a while but there seems to be a very small number of people who've had my issue and pretty much none of them had solutions that worked.
Here's my code:
import cv2
from time import sleep as wait
import numpy as np
lastFrame = "foobaz"
i = 0
#My webcam is on index 1, this isn't (at least shouldn't) be the issue. Make sure to set it back to 0 if you are testing
vid = cv2.VideoCapture(1)
#A placeholder black image for the 'subract' imshow window
black = np.zeros((512,512,3), np.uint8)
while(True):
wait(0.5)
ret, frame = vid.read()
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
blurframe = cv2.GaussianBlur(frame,(25,25),0)
#Makes sure the lastFrame has been assigned, if not set it as placeholder black image.
if lastFrame != "foobaz":
#Subtracts current frame and the last frame to find difference.
subFrame = cv2.subtract(blurframe,lastFrame)
else:
subFrame = black
#Assigns the next lastFrame
lastFrame = blurframe
#Gets the threshold of the subtracted image
ret,thresh1 = cv2.threshold(subFrame,40,255,cv2.THRESH_BINARY)
#Sets the thresholded image to grayscale if the loop was ran for the first time.
if i==0:
thresh1 = cv2.cvtColor(thresh1, cv2.COLOR_BGR2GRAY)
i+=1
#This is where issues arize. I'm trying to apply a bounding box using a contour but it always errors at line 44.
contours = cv2.findContours(thresh1, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)[0]
print(len(contours))
x,y,w,h = cv2.boundingRect(contours)
cv2.rectangle(frame,(x,y),(x+w,y+h),(0,255,0),2)
cv2.imshow('frame',frame)
cv2.imshow('subtract',thresh1)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
I saw that some other posts had the contour type() so here it is:
type(contours) = <class 'list'>
CLOSED: I found out the issue. You have to iterate contours for it to work.
i want to remove the duplication of objects, so when the camera opens it captures the first frame and save on the disk, than untill next object appears in the scene it saves the next object frame (does not save the same frame consecutively).
i have written a code to compare two consecutive frames of webcam, i want to store one frame in an array (max limit 3) to compare it with current frame. so the first frame will be saved on the disk and it compares untill the next object appears(used threshold value for this purpose)
How can i save the frame to an array and compare with current frame?
from skimage.metrics import structural_similarity
import imutils
import sys
import datetime
import cv2
import time
import numpy as np
cap = cv2.VideoCapture(0)
while (True):
# Capture frame-by-frame
ret, frame1 = cap.read(0) # first image
time.sleep(1/50) # slight delay
ret, frame2 = cap.read(0) # second image
gray1 = cv2.cvtColor(frame1, cv2.COLOR_BGR2GRAY)
gray2 = cv2.cvtColor(frame2, cv2.COLOR_BGR2GRAY)
# compute the Structural Similarity Index (SSIM) between the two
# images, ensuring that the difference image is returned
(score, diff) = structural_similarity (gray1, gray2, full=True)
diff = (diff * 255).astype ("uint8")
print ("SSIM: {}".format (score))
# threshold the difference image, followed by finding contours to
# obtain the regions of the two input images that differ
thresh = cv2.threshold (diff, 0, 255,
cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1]
if np.mean (thresh) < 0.4 :
print ("New object Detected")
date_string = datetime.datetime.now ( ).strftime ("%Y-%m-%d-%H:%M:%S")
cv2.imwrite ('img/img-' + date_string + '.png', frame2[y:y+h+30, x:x+w+30])
# Display the resulting frame
cv2.imshow ('frame1', frame1)
cv2.imshow('frame2', frame2)
cv2.imshow ("Diff", diff)
cv2.imshow ("Thresh", thresh)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# When everything is done, release the capture
video_capture.release()
cv2.destroyAllWindows()
Not hard.
Actually, you can get the image as a NumPy array.
The shape is (720, 1280, 3).
To save it, try this
...
ret, frame1 = cap.read(0) # first image
print(frame1.shape)
rgb_frame1 = frame1[..., ::-1]
im = Image.fromarray(rgb_frame1)
im.save("your_file.jpeg")
time.sleep(1/50) # slight delay
...
Note: you need to change the channel order or you will get a blue image. Because the original channel is in BRG format.
Then you can store the frame:
I'm using OpenCV/Python and I'm trying to add a number to image.
My code is:
import cv2
import numpy as np
import math
from matplotlib import pyplot as plt
img = cv2.imread('messi.jpg',0)
img2 = img
img2 = cv2.add(img2, np.uint8([50]))
I got the next error:
OpenCV Error: Assertion failed (type2 == CV_64F && (sz2.height == 1 || sz2.heigh
t == 4)) in cv::arithm_op, file C:\builds\master_PackSlaveAddon-win64-vc12-stati
c\opencv\modules\core\src\arithm.cpp, line 1989
Traceback (most recent call last):
File "lab3_examples.py", line 27, in <module>
img2 = cv2.add(img, np.uint8([50]))
cv2.error: C:\builds\master_PackSlaveAddon-win64-vc12-static\opencv\modules\core
\src\arithm.cpp:1989: error: (-215) type2 == CV_64F && (sz2.height == 1 || sz2.h
eight == 4) in function cv::arithm_op
The image I'm using is messi.jpg
Instead, if I use img2 = np.add(img2, np.uint8([50])) intensities that pass the value 255 the value % 255 result, e.g. 260%255=4 the pixel's value is set to 4 instead of 255. As a result, white pixels are turned to black!
Here is the faulty resulted image.
Any ideas please?
In C++ for this purpose saturate_cast(...) is used.
In Python simply
img2 = cv2.add(img2, 50)
will do, if you want to increase brightness for gray-scale image. If implied to colored, color balance will be shifted. For colored image, to save the balance, good answer is by Alex, Bill Grates:
How to fast change image brightness with python + OpenCV?
The only remark - next part of code are not nessessary:
v[v > 255] = 255
v[v < 0] = 0
in my case (Python3,Opencv4).
I would suggest convert the BGR image to HSV image:
hsv= cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
Then split the channels using:
h_channel, s_channel, v_channel = cv2.split(hsv)
Now play with the h_channel:
h_channel + = 20 #---You can try any other value as well---
Now merge the channels back together again:
merged = cv2.merge((h_channel , s_channel , v_channel ))
Finally convert the image back to BGR and display it:
Final_image = cv2.cvtColor(merged, cv2.COLOR_HSV2BGR)
cv2.imshow('Final output', Final_image)
You will see an enhanced or a dimmed image depending on the value you add.
Hope it helps.... :D