Warp an image from given coordinates - OpenCV Python - python

Im learning OpenCV at the moment. The goal of this exercise is to take the 4 corner points of a Pokercard from a laying perspective and warping it flat in front of you.
As you can see I have the coordinates mapped out in pts1/ corners assigned correctly (It seems like that at least, after checking).
After outputting imgWarped it throws the error:
traceback (most recent call last):
File "C:\Users\draco\PycharmProjects\Reader\main.py", line 101, in <module>
imgWarped = cv2.warpPerspective(img,matrix,(width,height))
cv2.error: OpenCV(4.4.0) C:\Users\appveyor\AppData\Local\Temp\1\pip-req-build-95hbg2jt\opencv\modules\imgproc\src\imgwarp.cpp:3143: error: (-215:Assertion failed) _src.total() > 0 in function 'cv::warpPerspective'
The documentations online did not help me much resolving this problem. What does my error message actually mean and how does it happen? Is there a better practice?
Here is the code:
import cv2
import numpy as np
img = cv2.imread("Resources/cards.jpg")
width,height = 250,350
pts1 = np.float32([[124,161],[189,155],[200,231],[135,245]])
pts2 = np.float32([[0,0],[width,0],[width,height],[0,height]])
matrix = cv2.getPerspectiveTransform(pts1,pts2)
---Here is the error --> imgWarped = cv2.warpPerspective(img,matrix,(width,height))
cv2.imshow("Warped Img", imgWarped)
cv2.waitKey(0)

I have used your code with my own image to regenerate the error, but it worked fine.
You can either post to us your input image, or make sure the point you select is not larger than your image it self, coz I can see that you are hard coding the points

Related

Error using OpenCV for Connected Components on numpy arrays

I'm trying to do a connected component analysis on an image using OpenCV in python. The images are in a '.czi' format so I am using aicsimageio to import the file into numpy array. However, I keep receiving the error:
OpenCV(4.6.0) D:\a\opencv-python\opencv-python\opencv\modules\imgproc\src\connectedcomponents.cpp:5632: error: (-215:Assertion failed) iDepth == CV_8U || iDepth == CV_8S in function 'cv::connectedComponents_sub1'
Below is some code similar to what I am trying to do. I will just create an numpy array for simplicity (instead of importing the image).
import numpy as np
import cv2
test = np.random.rand(512,512)
(T, thresh) = cv2.threshold(test, 0.5, 255, cv2.THRESH_BINARY)
num_labels, labels = cv2.connectedComponents(thresh)
This returns the error described above on the final line of code. The error seems to be something to do with the fact that the image wasn't imported using OpenCV, as I have got the same code to work when importing a random '.jpg' using OpenCV. I'm not sure why, since importing the '.jpg' using OpenCV returns a numpy array, i.e.:
image = cv2.imread(file)
type(thresh) == type(image)
returns True
Any help on how to fix this would be much appreciated!

why say empty function 'resize'?

the error that i get is .
error: OpenCV(4.1.2) /io/opencv/modules/imgproc/src/resize.cpp:3720: error: (-215:Assertion failed) !ssize.empty() in function 'resize'
fname_images = np.array(df_skin['image_id'])
file_to_read =('/content/drive/MyDrive/DATASET/HAM10000_images_part_1')+str(fname_images[0])+'.jpg'
import cv2
from cv2 import imread
from cv2 import resize
img = imread(file_to_read)
img2 = resize(img,(100,100))
# show one exampe image
plt.figure(figsize=(10,5))
plt.subplot(1,2,1)
plt.imshow(img[:,:,::-1])
plt.title('Original image')
plt.subplot(1,2,2)
plt.imshow(img2[:,:,::-1])
plt.title('Resized image for DenseNet')
plt.show()
imread() won't throw an exception if it can't find the image file -- it just returns None. The error occurs when you try to pass this to resize().
I think the pathname to the image file is wrong -- is HAM10000_images_part_1 a directory? If so, you forgot to add a slash after, and so the code tries to read an image named something like HAM10000_images_part_1bicycle.jpg which of course does not exist.
Try using Pillow and doing the .resize((x, y)) on it. And also check the path to make sure everything is good.

opencv read image assertion failed

I am a newbie to python and opencv.
trying to read image.
here is my code :-
import cv2
import numpy
img = cv2.imread('Test1.jpg',0)
cv2.imshow('image',img)
cv2.waitKey(0)
cv2.destroyAllWindows()
here is the error generated :-
OpenCV Error: Assertion failed (size.width>0 && size.height>0) in imshow, file /opt/concourse/worker/volumes/live/68762549-a7cd-401a-4fc4-6547354af396/volume/opencv_1512680491081/work/modules/highgui/src/window.cpp,
line 331 Traceback (most recent call last): File
"/Users/vinayak/PycharmProjects/Python_test1/test_img.py", line 4, in
cv2.imshow('image',img) cv2.error: /opt/concourse/worker/volumes/live/68762549-a7cd-401a-4fc4-6547354af396/volume/opencv_1512680491081/work/modules/highgui/src/window.cpp:331:
error: (-215) size.width>0 && size.height>0 in function imshow
please help me identify the fault. thanks in advance !
This error means you didnĀ“t loaded the image and img is empty.
There is a known error in imread for cv2. You can try replacing the imread call with this portion :
import matplotlib.pyplot as plt
img = plt.imread('Test1.jpg')
matplotlib does not have the same error on cv2.
The code is correct, this is the right way to load and display an image unsing OpenCV in Python, the additional argument you passed (0) means you're loading the image as grayscale and is the numeric value for the enum cv.IMREAD_GRAYSCALE
opencv load image tutorial
link to enums
Just for the sake of completeness, here the basic code I tested
import cv2 as cv
img = cv.imread('C:\\path\\to\\my\\Image\\image.bmp',0)
cv.imshow('image',img)
cv.waitKey(0)
cv.destroyAllWindows()
Due to this, the issue is most probably related to the path your're passing to cv.imread function
Are you sure your image is in the same working directoy you're
using?(and I bet is not...)
Did you try to change the relative path you gave with a complete absolute
path?

VideoCapture Error: vidcap.Error: Cannot set capture resolution

from VideoCapture import Device
cam = Device()
cam.setResolution(320, 240)
cam.saveSnapshot('demo.jpg')
I use VideoCapture in Windows Python2.7 .I do not know what`s wrong.How do I solve this problem.
Traceback (most recent call last):
File "D:/ideaProject/python_workspace/webcap/webcap/test/vc.py", line 8, in <module>
cam.setResolution(320, 240)
File "D:\SoftWare\Python27\lib\VideoCapture.py", line 90, in setResolution
self.dev.setresolution(width, height)
vidcap.Error: Cannot set capture resolution.
After I read the VideoCapture.py with a deep look,I find a solution :
from VideoCapture import Device
cam = Device()
cam.getImage(timestamp=0).resize((320, 240)).save('demo.jpg', quality=80)
I can get the right size of the photo.Perhaps I use wrong method.
I have a question, your solution looks more like a workaround. I guess you didn't change your camera's resolution, what your code did is to use your camera to capture an original picture and by using resize() function to change the captured picture's size then. That means, what you are doing looks like you capture a picture first(which doesn't have your desired resolution), then you go to edit that captured picture. If I'm wrong, I appreciate you can point that out cause I'm faced with this problem, too.

cvtColor fails assertion scn == 3 || scn ==4, but the image does have 3 channels and exists

I'm trying to run face detection on a Raspberry Pi, so I'm trying to find the fastest way to do everything. (every millisecond counts on a 700MHz processor!)
I made a quick speedtest that timed out the various options I need to check, which are:
Get webcam picture (choices are pygame.camera or openCV's cv2.VideoCapture)
Resize, convert to grayscale, and (if needed) convert to numpy and rotate.
It sounds odd, but for capturing a picture, pygame.camera is about 60ms faster than openCV on the raspberry pi.
Assuming that the extra conversion from a pygame surface to numpy, plus the 90 degree rotation, takes less than 60ms, it would be worth it to go with a mix.
The issue here is that I'm getting an odd cvtColor error, claiming my numpy ndarray (the backend for opencv 2.0 at the moment) does not have 3 or 4 channels.
This is odd, because I print out the shape of the ndarray right before I call cvtColor, and it has 3 channels. I can only assume I'm missing something incredibly obvious.
Here's the pared down code.
import pygame
import cv2
import numpy
from pygame import camera
pygame.init()
pygame.camera.init()
#get one shot from pygame camera
cam_list = pygame.camera.list_cameras()
pywebcam = pygame.camera.Camera(cam_list[0],(640,480))
pywebcam.start()
image = pywebcam.get_image()
for z in xrange(50):
image = pywebcam.get_image()
pywebcam.stop()
if image:
#numpy (convert to numpy as fast as possible)
numpy_image=pygame.surfarray.array3d(image)
print(numpy_image.shape)
numpy_image=cv2.cvtColor(numpy_image,cv2.COLOR_BGR2GRAY)
numpy_image = cv2.resize(numpy_image, (0,0), fx=0.25, fy=0.25)
numpy_image = numpy.rot90(numpy_image,3)
EDIT: Removed a bunch of code. The new code has removed all the profiling.
The output I get from this program is:
Average time in range: 58.64 ms.
Pausing to ensure webcam is freed.
Average time in range: 115.56 ms.
(480, 640, 3)
Pure NumPy
0 ms to printing shape.
39 ms to convert to grayscale.
16 ms to resize.
0 ms to rotate.
58 total ms.
(640, 480, 3)
OpenCV Error: Assertion failed (scn == 3 || scn == 4) in cvtColor, file /build/opencv-XZa2gn/opencv-2.3.1/modules/imgproc/src/color.cpp, line 2834
Traceback (most recent call last):
File "profile.py", line 72, in <module>
numpy_image=cv2.cvtColor(numpy_image,cv2.COLOR_BGR2GRAY)
cv2.error: /build/opencv-XZa2gn/opencv-2.3.1/modules/imgproc/src/color.cpp:2834: error: (-215) scn == 3 || scn == 4 in function cvtColor
What's going on here?
Found the answer. Apparently, numpy doesn't actually update the ndarray when you work on them, it just holds temporary changes in mind. Things are nice and fast that way.
While the C++ version of opencv 2.0 can handle that, the python bindings cannot- and since pygame's surfarray code works off numpy, any sort of situation where you go pygame->opencv is going to hit that problem.
With that said, all you need to do is call numpy.copy() after you call pygame.surfarray.array3d().
The new copy will have none of these temporary changes. For that reason, don't bother with array3d(), just use pixels3d()- you have to make a copy anyway, so don't make two.
For more information, I think the temporary changes were called 'strides' or something of the sort.

Categories

Resources