pyxploiter / Barcode-Detection-and-Decoding

Barcode detection and decoding using openCV and Zbar.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

TypeError: Expected cv::UMat for argument 'contour'

Matt-Payne opened this issue · comments

Getting an error barcode_opencv.py --image bilet.jpg
Traceback (most recent call last):
File "detect_barcode_opencv.py", line 62, in
c = sorted(cnts, key = cv2.contourArea, reverse = True)[0]
TypeError: Expected cv::UMat for argument 'contour'

I had to remove two returns from cnts = cv2.findContours as I believe it has changed to return just 1 item. I believe the error has to do with cnts being a tuple and not a list. I've seen others use imutils to turn into a list, but it has not worked on my images.

Hi @Matt-Payne,
This is a problem with OpenCV version. The current implementation works fine for OpenCV 3.4.x

cv2.findCountours returns 3 values (im, contours, hierarchy) in OpenCV 3.4.x
but this function returns 2 values (contours, hierarchy) in OpenCV 4.x

In your case, it seems that you are replacing the line:
im2,cnts,hierarchy = cv2.findContours(closed.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
with
cnts= cv2.findContours(closed.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
which means 'cnts' is a tuple containing two values: (contours, hierarchy) that is causing the error.

Solution:
I would suggest to change the above cv2.findContours line with following line:
cnts,hierarchy = cv2.findContours(closed.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
and do not change any other line. This should work fine.

Let me know if this solves your issue.

Seems to work, appreciate it. Any suggestions to help with images similar to the one below? I've tried to change the threshold to be more intense.
cardscan

Accidentally closed the issue!

Anyways,

  1. I am resizing (down sampling) my images in my code because the images were of larger dimensions. In your case, it seems that you have smaller images so you might not have to resize the input image.
  2. You have to change the StructuringElement according to your sample images.

erode
I replaced the resizing with cropping, considering I know the barcode will be in a similar spot everytime. It looks from the --show images that the erosion and dialate is giving an image that looks like a barcode itself.

erode
I replaced the resizing with cropping, considering I know the barcode will be in a similar spot everytime. It looks from the --show images that the erosion and dialate is giving an image that looks like a barcode itself.

Provide me some of your sample images and let me give it a try.

Hello, sorry for the wait, I apprieate the help
chuckcroppedover
unitas
chuck

i am facing same problem even when i am using opencv 3.4.9.31

i am facing same problem even when i am using opencv 3.4.9.31

I have updated the code. I will work for all opencv versions now.

@pyxploiter Hi I was facing the same issue. I changed:
(new, cnts, _) = cv2.findContours(edged.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
TO
(new, cnts) = cv2.findContours(edged.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)

Then i wrote:
cnts = cnts.astype(np.uint32)

Now I am facing error in the following line:
cnts=sorted(cnts, key = cv2.contourArea, reverse = True)[:30]

TypeError: Expected Ptrcv::UMat for argument 'contour'

Can you suggest what you did to make your code work?

@pyxploiter Hi I was facing the same issue. I changed:
(new, cnts, _) = cv2.findContours(edged.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
TO
(new, cnts) = cv2.findContours(edged.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)

Then i wrote:
cnts = cnts.astype(np.uint32)

Now I am facing error in the following line:
cnts=sorted(cnts, key = cv2.contourArea, reverse = True)[:30]

TypeError: Expected Ptrcv::UMat for argument 'contour'

Can you suggest what you did to make your code work?

@vinayak93999 Please update the line such as:
(cnts, new) = cv2.findContours(edged.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)[-2:]

Since, findContours will return a tuple of two values (contours, hierarchy) in this case.

(cnts, new) = cv2.findContours(thresh_delta.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)[-2:]

for contour in cnts, new:
    if cv2.contourArea(contour) < 1000:
        continue

it does not work

Hi @Matt-Payne,
This is a problem with OpenCV version. The current implementation works fine for OpenCV 3.4.x

cv2.findCountours returns 3 values (im, contours, hierarchy) in OpenCV 3.4.x
but this function returns 2 values (contours, hierarchy) in OpenCV 4.x

In your case, it seems that you are replacing the line:
im2,cnts,hierarchy = cv2.findContours(closed.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
with
cnts= cv2.findContours(closed.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
which means 'cnts' is a tuple containing two values: (contours, hierarchy) that is causing the error.

Solution:
I would suggest to change the above cv2.findContours line with following line:
cnts,hierarchy = cv2.findContours(closed.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
and do not change any other line. This should work fine.

Let me know if this solves your issue.

Thanks man, it worked smoothly for me