openCV - camera view window has different size of camera resolution - python

I have a 720p resolution camera and I'm trying to open the camera in a view window in openCV. here's the code:
while(True):
ret, frame = vid.read()
if render_poly:
frame = cv2.polylines(frame, [pts],
isClosed, color, thickness)
cv2.imshow('window', frame)
key = cv2.waitKey(1) & 0xFF
if key == ord('q'):
break
elif key == ord('p'):
render_poly = not render_poly
Before that, I tried to ajust the view window with this code (720p resolution):
vid = cv2.VideoCapture(0)
vid.set(cv2.CAP_PROP_FRAME_HEIGHT, 720)
vid.set(cv2.CAP_PROP_FRAME_WIDTH, 1280)
What I expected is 1280x720 view window size, but for some reason I got 1600x900 which caused incorrect positioning of the polygon I'm trying to render, and to solve that I needed to adjust its coordinates by multiplying it with the scale of 1280/1600 in width and 720/900 in height.
Can I skip that proccess (which will be more in the future project) and just to render the camera view on a window with its same resolution size? is it a good idea?

Related

How to correctly display OpenCv Portrait mode in Full screen?

I am trying to corectly show Landscape and Portrait mode with OpenCv in Python.
I am using a small 2.8" TFT screen with a resolution of 240 x 320 attached to a micro computer that is running Debian buster.
The webcam I am using has the following supported resolutions:
640x480 352x288 320x240 176x144 160x120
With the cv2.WND_PROP_FULLSCREEN the screen starts with grey edges at top and bottom.
cap = cv2.VideoCapture(0)
cap.set(cv2.CAP_PROP_BUFFERSIZE, 1)
cv2.namedWindow('default', cv2.WND_PROP_FULLSCREEN)
cv2.setWindowProperty('default', cv2.WND_PROP_FULLSCREEN,
cv2.WINDOW_FULLSCREEN)
while True:
ret, frame = cap.read()
if viewMode == "normal":
cv2.imshow("default", frame)
Then I rotate it with cv2.ROTATE_90_CLOCKWISE to get the Landscape mode.
elif viewMode == "landscape":
frame = cv2.rotate(frame, cv2.ROTATE_90_CLOCKWISE)
cv2.imshow("default", frame)
It works fine with proper scaling without stretching in both X and Y axes.
To get the Portrait mode in full screen, I use cv2.WINDOW_FREERATIO. But it streches in Y axis and the display is not good.
elif viewMode == "portrait":
cv2.namedWindow('freeratio', cv2.WINDOW_FREERATIO)
cv2.setWindowProperty(
'freeratio', cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN)
cv2.imshow("freeratio", frame)
What is the correct way to show Portrait mode in this case without streching and maintaining proper scaling in both axes?
Here's my full code below:
import cv2
# viewMode = "normal"
# viewMode = "landscape"
viewMode = "portrait"
cap = cv2.VideoCapture(0)
cap.set(cv2.CAP_PROP_BUFFERSIZE, 1)
cv2.namedWindow('default', cv2.WND_PROP_FULLSCREEN)
cv2.setWindowProperty('default', cv2.WND_PROP_FULLSCREEN,
cv2.WINDOW_FULLSCREEN)
while True:
ret, frame = cap.read()
if viewMode == "normal":
cv2.imshow("default", frame)
elif viewMode == "landscape":
frame = cv2.rotate(frame, cv2.ROTATE_90_CLOCKWISE)
cv2.imshow("default", frame)
elif viewMode == "portrait":
cv2.namedWindow('freeratio', cv2.WINDOW_FREERATIO)
cv2.setWindowProperty(
'freeratio', cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN)
cv2.imshow("freeratio", frame)
if cv2.waitKey(5) & 0xFF == 27:
break
cap.release()
Note: I have tried most suggestions I found on other similar posts/threads but to no avail. Resizing/cropping or manually setting the resolution does not help. It either gives me the greyed borders on topand bottom or streched out. Could it be any setting in the webcam/Debian that's causing the issue?
Any help/suggestions is appreciated.

how to resize live video in python cv2 using .set()?

I am learning opencv with https://www.youtube.com/watch?v=oXlwWbU8l2o&ab_channel=freeCodeCamp.org this tutorial and I arrived at part 3 (resizing and rescaling). Towards the end he creates this function which should be better for live video. The function doesn't return anything and he doesn't show how it works. The funtion is change_res(width, height) and I think it should be called in the while loop for frame_resized.
import cv2 as cv
def rescale_frame(frame, scale): # works for image, video, live video
width = int(frame.shape[1] * scale)
height = int(frame.shape[0] * scale)
dimensions = (width, height)
return cv.resize(frame, dimensions, interpolation=cv.INTER_AREA)
def change_res(width, height): # works only for live video
capture.set(3, width)
capture.set(4, height)
capture = cv.VideoCapture(0) # integer to capture from webcam, path to capture video file
while True:
isTrue, frame = capture.read()
frame_resized = rescale_frame(frame, scale=.2) # this line
cv.imshow("Video", frame)
cv.imshow("Video Resized", frame_resized)
if cv.waitKey(20) & 0xFF == ord("q"): # press "q" key to exit loop
break
capture.release()
cv.destroyAllWindows()
Thanks to #Dan MaĊĦek 's comment I managed to understand.
The .set() method changes the resolution of the camera, it doesnt need to be in the while loop because capture = cv.VideoCapture(0) keeps going by defeault forever unless capture.release() is called.
import cv2 as cv
def rescale_frame(frame, scale): # works for image, video, live video
width = int(frame.shape[1] * scale)
height = int(frame.shape[0] * scale)
dimensions = (width, height)
return cv.resize(frame, dimensions, interpolation=cv.INTER_AREA)
capture = cv.VideoCapture(0) # integer to capture from webcam, path to capture video file
capture.set(3, 1440)
while True:
isTrue, frame = capture.read()
frame_resized = rescale_frame(frame, scale=.2)
cv.imshow("video with set", frame)
cv.imshow("Video Resized", frame_resized)
if cv.waitKey(20) & 0xFF == ord("q"): # press "q" key to exit loop
break
capture.release() # stop capturing the image/video
cv.destroyAllWindows() # close windows
So, I wanted a small and a big window showing what the webcam was capturing. Currently this code captures the video, makes it 2560x1440 (with .set) which is enormous and then it takes those frames and rescales them with the rescale_frame function to make it smaller.
I found out that this .set() method is more efficient for a single video but if I want two I should show as small the default one and then use rescale_frame to make it bigger.

Sending ROS messages through a cv2 python script

I am trying to implement a robotic solution, where the user will click on a point through a camera feed of an area and the mobile 4 wheel robot will path its way to that location.
I have created the part of translating video pixel coordinates to ground coordinates through the use of the homograph transformation and would like to implement the part of sending the ground coordinates to RViz.
The part of calculating the ground coordinates is shown bellow:
global h
font = cv2.FONT_HERSHEY_SIMPLEX #Loading neccessary fonts
with open("save.h", "rb") as f:
h = load(f)
print "Homographic matrix loaded successfully."
def draw_circle2(event,x,y,flags,param):
global h,mouseX,mouseY, num_of_points, complete,np_coord_on_screen,np_coord_on_ground, myImage, emptyFrame, coord_on_screen, coord_on_ground
if event == cv2.EVENT_LBUTTONDBLCLK:
a = np.array([[x, y]], dtype='float32')
a = np.array([a])
pointOut = cv2.perspectiveTransform(a, h) #Calculation of new point location
loc_pointOut = tuple(pointOut)
pointOut=(loc_pointOut[0][0][0],loc_pointOut[0][0][1]) #Point on ground
print "Current Location: "+str(pointOut)
cv2.imshow('Video',emptyFrame) #Showing emptyFrame
cv2.circle(myImage,(x,y),4,(255,0,0),-1) #Draw a circle on myImage
cv2.putText(myImage,(str((round(pointOut[0],2)))+","+str(round(pointOut[1],2))), (x-5,y-15),font, 0.4,(0,255,0)) #Draw the text
cv2.imshow('Video',myImage) #Showing resulting myImage
myImage = emptyFrame.copy()
# Initial code
# Showing first frame on screen
raw_input("Press any key...")
clear_all()
cv2.namedWindow('Video') #Naming the window to use.
cv2.setMouseCallback('Video',draw_circle2) #Set mouse callBack function.
ret, frame = cap.read() #Get image from camera
if (ret): #If frame has image, show the image on screen
global myImage, emptyFrame
myImage = frame.copy()
emptyFrame = frame.copy()
cv2.imshow('Video',myImage) # Show the image on screen
while True: # making a loop
if cv2.waitKey(1) & 0xFF == ord('q'):
break
if (cv2.waitKey(1) & 0xFF == ord('c')):
#Deleting points from image
cv2.imshow('Video',emptyFrame) #Show the image again, deleting all graphical overlays like text and shapes
coord_on_screen = [] #Resetting coordinate lists
coord_on_ground=[] #Resetting coordinate lists
if (cv2.waitKey(1) & 0xFF == ord('s')):
cap.release()
cv2.destroyAllWindows()
init()
# When everything done, release the capture
cap.release()
cv2.destroyAllWindows()
So, pointOut is the point on the ground (example: (2,4) m)
I need some directions on how to implement the creation of a node and the transmission of the pointOut Marker message to a ROS topic in my code.
My configuration is ROS Kinetic Kame, Python 2.7

Python Opencv crops input image from usb camera

Im trying to create a tool that will take images from stereo cameras (connected to a sync board) with python and opencv.
When im looking at the image i get from opencv it seems different then what i get with windows camera app.
both set to the same resolution. what am i missing?
cap = cv2.VideoCapture(0)
# cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1280)
#
# cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 720)
while 1:
ret, frame = cap.read()
# cv2.imshow("frame",frame)
cv2.imwrite('test.bmp',frame)
if cv2.waitKey(20) & 0xFF == ord('q'):
break
width = cap.get(cv2.CAP_PROP_FRAME_WIDTH)
height = cap.get(cv2.CAP_PROP_FRAME_HEIGHT)
print('size:', width, height)
both images are 1344x376

Using a webcam and OpenCV-Python 3.4.0, how do I keep a drawing function in one window from appearing on to another window?

Two Windows
Hello everyone,
On the right of the picture link named "Two Windows", I have a window named 'frame' which shows a green square and a cyan circle. On the left, there is a window named 'binary' which shows the square and circle in white.
The binary window shows in white objects that are moving.
What can I do so that the drawing functions do not show in the 'binary' window and only stay in the 'frame' window?
I'd greatly appreciate any help I can receive.
import numpy as np
import cv2
cap = cv2.VideoCapture(0)
ret, last_frame = cap.read()
if last_frame is None:
exit()
while(cap.isOpened()):
ret, frame = cap.read()
if frame is None:
exit()
binary = cv2.absdiff(last_frame, frame)
binary = cv2.cvtColor(binary, cv2.COLOR_BGR2GRAY)
ret, binary = cv2.threshold(binary,50,255,cv2.THRESH_BINARY)
last_frame = frame.copy()
#Rectangle
frame = cv2.rectangle(frame,(0,0),(320,240),(0,255,0),3)
#Circle
vRow, vCol, vCH = frame.shape
cirR = 30
cirRowPos = int(vRow/2)
cirColPos = int(vCol-cirR) - int(vCol*0.05)
frame = cv2.circle(frame,(cirColPos, cirRowPos), cirR, (255,255,0), 3)
cv2.imshow('frame', frame)
cv2.imshow('binary', binary)
if cv2.waitKey(33) >= 0:
break
last_frame = frame
cap.release()
cv2.destroyAllWindows()
I deleted the line 'last_frame = frame" and I added "last_frame = frame.copy()" before my drawing functions.

Categories