I'm working on a program that detects circular shapes in images. I decided a Hough Transform would be the best, and I found one in the OpenCV library. The problem is that when I try to use it I get an error that I have no idea how to fix. Is OpenCV for Python not fully implemented? Is there a fix to the library I need for the program to work?
Here's the code:
import cv
#cv.NamedWindow("camera", 1)
capture = cv.CaptureFromCAM(0)
while True:
img = cv.QueryFrame(capture)
gray = cv.CreateImage(cv.GetSize(img), 8, 1)
edges = cv.CreateImage(cv.GetSize(img), 8, 1)
cv.CvtColor(img, gray, cv.CV_BGR2GRAY)
cv.Canny(gray, edges, 50, 200, 3)
cv.Smooth(gray, gray, cv.CV_GAUSSIAN, 9, 9)
storage = cv.CreateMat(1, 2, cv.CV_32FC3)
#This is the line that throws the error
cv.HoughCircles(edges, storage, cv.CV_HOUGH_GRADIENT, 2, gray.height/4, 200, 100)
#cv.ShowImage("camera", img)
if cv.WaitKey(10) == 27:
break
And here is the error I'm getting:
OpenCV Error: Null pinter () in unknown function,
file ..\..\..\..\ocv\openc\src\cxcore\cxdatastructs.cpp, line 408
Traceback (most recent call last):
File "ellipse-detect-webcam.py", line 20, in
cv.HoughCircles(edges, storage, cv.CV_HOUGH_GRADIENT, 2, gray.height/4, 200, 100)
cv.error
Thanks in advance for the help.
For what it's worth, I've found that cv.HoughCircles aborts if it can't detect a circular shape in the image, instead of gracefully returning an empty list.
Are the images valid?
Can you display them (the original and the grayscaled)
Otherwise are you sure the args to the function are correct? Are you passing pointers or references correctly
The storage must to be bigger, I thought that cvMat isn't dinamically allocated so you have to for example change the line:
storage = cv.CreateMat(1, 2, cv.CV_32FC3)
to:
storage = cv.CreateMat(1, img.rows * img.cols, cv.CV_32FC3)
Related
if not len(blurred.shape) == 2:
gray = cv2.cvtColor(blurred, cv2.COLOR_RGB2GRAY)
else:
gray = blurred
edge = cv2.Canny(gray, 50, 150)
circles = AHTforCircles(edge,center_threhold_factor=params[i]['center_threhold_factor'],score_threhold=params[i]['score_threhold'],min_center_dist=params[i]['min_center_dist'],minRad=params[i]['minRad'],
maxRad=params[i]['maxRad'],center_axis_scale=params[i]['center_axis_scale'],radius_scale=params[i]['radius_scale'],
halfWindow=params[i]['halfWindow'],max_circle_num=params[i]['max_circle_num'])
final_img = drawCircles(circles,blurred)
plt.imshow(final_img)
plt.axis('off')
plt.show()
edge = cv2.Canny(gray, 50, 150)
cv2.error: OpenCV(4.1.1)
C:\projects\opencv-python\opencv\modules\imgproc\src\canny.cpp:829:
error: (-215:Assertion failed) _src.depth() == CV_8U in function
'cv::Canny'
It would be helpfully to receive some description of your problem. What you are trying to do etc. When problem occurs. You know help us little bit before we can help you:)
An input image to the cv2.Canny() function has the wrong data type. It needs to be unsigned 8-bit integers (what OpenCV calls CV_8U), and you have something else (we can't see what from your code).
Change to cv2.Canny(gray.astype('uint8')) and that particular problem should go away.
Note though, that you might want to think about what data type your images have, and do this conversion somewhere else.
I've been working on building a machine learning algorithm to recognize images, starting by creating my own h5 database. I've been following this tutorial, and it's been useful, but I keep running into one major error - when using OpenCV in the image processing section of the code, the program is unable to save the processed image because it keeps flipping the height and width of my images. When I try to compile, I get the following error:
Traceback (most recent call last):
File "array+and+label+data.py", line 79, in <module>
hdf5_file["train_img"][i, ...] = img[None]
File "h5py/_objects.pyx", line 54, in h5py._objects.with_phil.wrapper
File "h5py/_objects.pyx", line 55, in h5py._objects.with_phil.wrapper
File "/Users/USER/miniconda2/lib/python2.7/site-packages/h5py/_hl/dataset.py", line 631, in __setitem__
for fspace in selection.broadcast(mshape):
File "/Users/USER/miniconda2/lib/python2.7/site-packages/h5py/_hl/selections.py", line 299, in broadcast
raise TypeError("Can't broadcast %s -> %s" % (target_shape, count))
TypeError: Can't broadcast (1, 240, 320, 3) -> (1, 320, 240, 3)
My images are supposed to all be sized to 320 by 240, but you can see that this is being flipped somehow. Researching around has shown me that this is because OpenCV and NumPy use different conventions for height and width, but I'm not sure how to reconcile this issue within this code without patching my installation of OpenCV. Any ideas on how I can fix this? I'm a relative newbie to Python and all its libraries (though I know Java well)!
Thank you in advance!
Edit: adding more code for context, which is very similar to what's in the tutorial under the "Load images and save them" code example.
The size of my arrays:
train_shape = (len(train_addrs), 320, 240, 3)
val_shape = (len(val_addrs), 320, 240, 3)
test_shape = (len(test_addrs), 320, 240, 3)
The code that loops over the image addresses and resizes them:
# Loop over training image addresses
for i in range(len(train_addrs)):
# print how many images are saved every 1000 images
if i % 1000 == 0 and i > 1:
print ('Train data: {}/{}'.format(i, len(train_addrs)))
# read an image and resize to (320, 240)
# cv2 load images as BGR, convert it to RGB
addr = train_addrs[i]
img = cv2.imread(addr)
img = cv2.resize(img, (320, 240), interpolation=cv2.INTER_CUBIC)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
# save the image and calculate the mean so far
hdf5_file["train_img"][i, ...] = img[None]
mean += img / float(len(train_labels))
Researching around has shown me that this is because OpenCV and NumPy use different conventions for height and width
Not exactly. The only thing that is tricky about images is 2D arrays/matrices are indexed with (row, col) which is opposite from normal Cartesian coordinates (x, y) that we might use for images. Because of this, sometimes when you specify points in OpenCV functions, it wants them in (x, y) coordinates---and similarly, it wants the dimensions of the image to be specified in (w, h) instead of (h, w) like an array would be made. And this is the case inside OpenCV's resize() function. You're passing it in (h, w) but it actually wants (w, h). From the docs for resize():
dsize – output image size; if it equals zero, it is computed as:
dsize = Size(round(fx*src.cols), round(fy*src.rows))
Either dsize or both fx and fy must be non-zero.
So you can see here that the number of columns is the first dimension (the width) and the number of rows is the second (the height).
The simple fix is just to swap your (h, w) to (w, h) inside the resize() function:
img = cv2.resize(img, (240, 320), interpolation=cv2.INTER_CUBIC)
I'm using OpenCV 3.0.0 and Python 3.4.3 to process a very large RGB image (107162,79553,3). While I'm trying to resize it using the following code:
import cv2
image = cv2.resize(img, (0,0), fx=0.5, fy=0.5, interpolation=cv2.INTER_AREA)
I had this error message coming up:
cv2.error: C:\opencv-3.0.0\source\modules\imgproc\src\imgwarp.cpp:3208: error: (-215) ssize.area() > 0 in function cv::resize
I'm certain there is image content in the image array because I can save them into small tiles in jpg format. When I try to resize just a small part of the image, there is no problem and I end up with correctly resized image. (Taking a rather big chunk (50000,50000,3) still won't work, but it will work on a (10000,10000,3) chunk)
What could cause this problem and how can I solve this?
So it turns out that the problem comes from one line in modules\imgproc\src\imgwarp.cpp:
CV_Assert( ssize.area() > 0 );
When the product of rows and columns of the image to be resized is larger than 2^31, ssize.area() results in a negative number. This appears to be a bug in OpenCV and hopefully will be fixed in the future release. A temporary fix is to build OpenCV with this line commented out. While not ideal, it works for me.
And I just recently found out that the above applies only to image whose width is larger than height. For images with height larger than width, it's the following line that causes error:
CV_Assert( dsize.area() > 0 );
So this has to be commented out as well.
Turns out for me this error was actually telling the truth - I was trying to resize a Null image, which was usually the 'last' frame of a video file, so the assertion was valid.
Now I have an extra step before attempting the resize operation, which is to do the assertion myself:
def getSizedFrame(width, height):
"""Function to return an image with the size I want"""
s, img = self.cam.read()
# Only process valid image frames
if s:
img = cv2.resize(img, (width, height), interpolation = cv2.INTER_AREA)
return s, img
Now I don't see the error.
Also pay attention to the object type of your numpy array, converting it using .astype('uint8') resolved the issue for me.
I know this is a very old thread but I had the same problem which was due spaces in the images names.
e.g.
Image name: "hello o.jpg"
weirdly, by removing the spaces the function worked just fine.
Image name: "hello_o.jpg"
I am having OpenCV version 3.4.3 on MacOS.
I was getting the same error as above.
I changed my code from
frame = cv2.resize(frame, (0,0), fx=0.5, fy=0.5)
to
frame = cv2.resize(frame, None, fx=0.5, fy=0.5)
Now its working fine for me.
This type of error also takes place because the resize is unable to get the image in simple
the directory of the image may be wrong.In my case I left the forward slash during providing the location of file and this error took place after I put the slash problem was solved.
For me the following work-around worked:
split the array up into smaller sub arrays
resize the sub arrays
merge the sub arrays again
Here the code:
def split_up_resize(arr, res):
"""
function which resizes large array (direct resize yields error (addedtypo))
"""
# compute destination resolution for subarrays
res_1 = (res[0], res[1]/2)
res_2 = (res[0], res[1] - res[1]/2)
# get sub-arrays
arr_1 = arr[0 : len(arr)/2]
arr_2 = arr[len(arr)/2 :]
# resize sub arrays
arr_1 = cv2.resize(arr_1, res_1, interpolation = cv2.INTER_LINEAR)
arr_2 = cv2.resize(arr_2, res_2, interpolation = cv2.INTER_LINEAR)
# init resized array
arr = np.zeros((res[1], res[0]))
# merge resized sub arrays
arr[0 : len(arr)/2] = arr_1
arr[len(arr)/2 :] = arr_2
return arr
You can manually place a check in your code. Like this:
if result != []:
for face in result:
bounding_box = face['box']
x, y, w, h = bounding_box[0], bounding_box[1], bounding_box[2], bounding_box[3]
rect_face = cv2.rectangle(frame, (x, y), (x+w, y+h), (46, 204, 113), 2)
face = rgb[y:y+h, x:x+w]
#CHECK FACE SIZE (EXIST OR NOT)
if face.shape[0]*face.shape[1] > 0:
predicted_name, class_probability = face_recognition(face)
print("Result: ", predicted_name, class_probability)
Turns out I had a .csv file at the end of the folder from which I was reading all the images.
Once I deleted that it worked alright
Make sure that it's all images and that you don't have any other type of file
In my case I did a wrong modification in the image.
I was able to find the problem checking the image shape.
print img.shape
In my case,
image = cv2.imread(filepath)
final_img = cv2.resize(image, size_img)
filepath was incorrect, cv2.imshow didn't give any error in this case but due to wrong path cv2.resize was giving me error.
I came across the same error message while I was trying to enlarge the image size. Assigning the image type as uint8 did the work for me and I was able to resize the image 30 times of its original size. Here is an example as a reference for anyone else who has such issue.
scale_percent = 3000
width = int(img.shape[1] * scale_percent / 100)
height = int(img.shape[0] * scale_percent /100)
dim = (width, height)
image = cv2.resize(img.astype('uint8'), dim, interpolation=cv2.INTER_AREA)
Same error message for me but issue was different:
The interpolation method 'INTER_AREA' was NOT compatible with int8 !
cv2.resize(frame_rgb, tuple([None, None]))
gives similar error. Notice the None values in the resizing tuple.
In my case there were some corrupt or not supported images. What i simple did is just check if it is not None than process it as shown below.
cv2.imread(image_path)
if img is not None:
cv2.resize(img,(150,150)) # You can give your own desired image size
I was working with 3 files: The python script, the image, and the trained model.
Everything worked when I moved these 3 files into their own folder instead of in the directory with the other python scripts.
I had the same error. Resizing the images resolved the issue. However, I used online tools to resize the images because using pillow to resize them did not solve my problem.
import numpy as np
import cv2
def resize(image, percentage):
img = image
fy=percentage
fx=percentage
img2 = cv2.resize(img, (0,0), fx, fy)
return cv2.img2
img = cv2.imread('test.png')
img2 = resize(img, 0.45)
cv2.imshow('image',img2)
cv2.waitKey(0)
cv2.destroyAllWindows()
Traceback (most recent call last):
File "C:\Users\Jay\Desktop\Portable Python\opencvprogram_ver1.py", line 14, in <module>
img2 = resize(img, 0.45)
File "C:\Users\Jay\Desktop\Portable Python\opencvprogram_ver1.py", line 10, in resize
img2 = cv2.resize(img, (0,0), fx, fy)
error: C:\builds\master_PackSlaveAddon-win32-vc12-static\opencv\modules\imgproc\src\imgwarp.cpp:3209: error: (-215) dsize.area() > 0 || (inv_scale_x > 0 && inv_scale_y > 0) in function cv::resize
Dear Python Council members,
I've been learning Python and OpenCV and I ran into a problem here.
I'm trying to see if it's possible to include an OpenCV function in my own function, but it seems like I'm doing this wrong. The traceback says something something about dsize.area in cv::resize, but this error message means very little too me because I do not know how this works in the smaller picture.
Can someone guide me in the right direction so the program works as I'd expect?
Thank you very much.
What you have looks almost right. Just change the last two lines of the function to:
img2 = cv2.resize(img, (0,0), fx=fx, fy=fy) # enter fx and fy as keyword arguments
return img2 # cv2.img2 was just a typo
Since fx and fy are not the 3rd and 4th arguments of the function, you have to specify them as keyword arguments.
I am trying to detect circles using a Hough transform with opencv.
When there is no circle in the scene I get a null pointer error. I can handle this with exceptions I think.
However, when there is a circle, trying to manipulate the storage object gives me errors.
For instance I have tried to convert it to a numpy array and most but not all of the time I get the following fatal error.
Some times frames do show correctly.
OpenCV Error: Bad argument (unrecognized or unsupported array type) in cvSetData,
file /build/buildd/opencv-2.3.1/modules/core/src/array.cpp,
My code
while True:
img = billy.get_frame()
# Convert from BGR to HSV
grey = cv.CreateImage(cv.GetSize(img), 8, 1)
cv.CvtColor(img, grey, cv.CV_BGR2GRAY)
cv2.cv.Smooth(grey, grey, cv.CV_GAUSSIAN, 7, 7)
circles = np.array([], dtype=np.float32)
storage = cv.CreateMat(1, 2, cv.CV_32FC3)
try:
cv.HoughCircles(grey, storage, cv.CV_HOUGH_GRADIENT, 2, grey.height/4, 200, 100)
for i in range(0,len(np.asarray(storage))):
cv.Circle(img, ( int(np.asarray(storage)[i][0][0]), int(np.asarray(storage)[i][0][1]) ), int(np.asarray(storage)[i][0][2]), cv.CV_RGB(255, 0, 0), 2, 8, 0 )
except:
pass
cv.ShowImage("threshholded", img )