updated: IndexError: индекс 0 выходит за пределы оси 0 с размером 0? - PullRequest
0 голосов
/ 06 января 2020

У меня есть вопросы по поводу следующих кодов: я хочу вернуть 2 значения в этой функции, одно из которых orig_image, что хорошо, другое - cx, cx - координата x центра наибольшего контура, который область в пределах определенного диапазона. Терминал говорит: «ValueError: слишком много значений для распаковки (ожидается 2)». (Решено) Появляется следующая проблема: «IndexError: index 0 выходит за пределы оси 0 с размером 0?» Могу ли я узнать причину и решение? Спасибо большое!

def findContours(image):
    orig_image = image.copy()
    image2 = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    ret, image2 = cv2.threshold(image2, 127, 255, 1)
    image2 = cv2.Canny(image2,30,200)
    # Find contours 
    contours, hierarchy = cv2.findContours(image2.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
    max_area = 200000000000000
    min_area = 100
    areaList=[]
    cxList=[]
    if contours is not None:
        for c in contours:    

            area = cv2.contourArea(c)
            if min_area < area < max_area:
                areaList.append(area)
                approx = cv2.approxPolyDP(c, 0.03*cv2.arcLength(c,True),False)

                cv2.drawContours(orig_image, [c], 0,(0,255,0), -1)
                # cv2.drawContours(orig_image, [c], 0,(225,0,0), -1)
                x,y,w,h = cv2.boundingRect(c)
                # cv2.rectangle(orig_image3,(x,y),(x+w,y+h),(0,0,255),2)
                cx=x+int(w/2)
                cxList.append(cx)
                cy=y+int(h/2)
                cv2.circle(orig_image, (cx,cy), 5, (0,0,255), -1) 
        if areaList:    
            maxArea=max(areaList)
            index=np.where(areaList==maxArea)
            targetCx= cxList[index[0][0]]
            return targetCx #this is where the problem occur

    return orig_image #this is where the problem occur

def main():
       targetCx , original_image = findContours(original_image) #this is where 
       the problem occur

Терминал:

targetCx , original_image = findContours(original_image)
ValueError: too many values to unpack (expected 2)

Если я изменю последнюю часть на:

if areaList:    
        maxArea=max(areaList)
        index=np.where(areaList==maxArea)
        targetCx= cxList[index[0][0]]
        return targetCx
else:
        return None
return orig_image 

Терминал показывает:

targetCx , original_image = findContours(original_image)
TypeError: cannot unpack non-iterable NoneType object

ОБНОВЛЕНИЕ

def findContours(image):
    orig_image = image
    image2 = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    ret, image2 = cv2.threshold(image2, 127, 255, 1)
    image2 = cv2.Canny(image2,30,200)
    # Find contours 
    contours, hierarchy = cv2.findContours(image2.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
    max_area = 200000000000000
    min_area = 100
    areaList=[]
    cxList=[]
    targetCx =None
    if contours is not None:
        for c in contours:    

            area = cv2.contourArea(c)
            if min_area < area < max_area:
                areaList.append(area)
                approx = cv2.approxPolyDP(c, 0.03*cv2.arcLength(c,True),False)

                cv2.drawContours(orig_image, [c], 0,(0,255,0), -1)
                # cv2.drawContours(orig_image, [c], 0,(225,0,0), -1)
                x,y,w,h = cv2.boundingRect(c)
                # cv2.rectangle(orig_image3,(x,y),(x+w,y+h),(0,0,255),2)
                cx=x+int(w/2)
                cxList.append(cx)
                cy=y+int(h/2)
                cv2.circle(orig_image, (cx,cy), 5, (0,0,255), -1) 

    if areaList:
        maxArea=max(areaList)
        index=np.where(areaList==maxArea)
        targetCx = cxList[index[0][0]]

    return targetCx,orig_image

ТЕРМИНАЛ:

targetCx = cxList[index[0][0]]
IndexError: index 0 is out of bounds for axis 0 with size 0

Ответы [ 2 ]

0 голосов
/ 06 января 2020

Технически ваша функция возвращает только один элемент за раз. Функция завершается при ударе одного возврата. Так что здесь было бы неплохо иметь двойные возвраты и оставить по одному в None в каждом разделе. Т.е. -

...
    if areaList:    
        maxArea=max(areaList)
        index=np.where(areaList==maxArea)
        targetCx= cxList[index[0][0]]
        return (None, targetCx) #x-coord is second

return (orig_image, None) #orig_image is first

, а затем выполните проверку, чтобы определить, с какой ветвью вы go. Таким образом, вы можете распаковать два значения (одно будет None), и возвращение не является проблемой.

original_image, targetCx = findContours(original_image)
if original_image is not None: 
    # do stuff with original_image
else:
    # do stuff with targetCx

Дайте мне знать, если это поможет!

0 голосов
/ 06 января 2020

Согласно документации , функция cv2.findContours () возвращает 3 значения (изображение, контуры, иерархия).

Но вы пытаетесь только распаковать контуры и иерархию, и это приводит к ошибке .
Чтобы это исправить, измените код на image, contours, hierarchy = cv2.findContours().
или просто сделайте _, contours, hierarchy = cv2.findContours(), чтобы не использовать возвращаемое изображение.

ОБНОВЛЕНО
Оригинал вопрос меняется при написании первого ответа.
В сообщении об ошибке написано: I(Python) expected function call will returns exactly two values, but actually more than two are returned.

Возвращаемое значение функции findContours может иметь несколько форм: None, targetCx, orig_image.
А на стороне вызова функции вы предполагаете, что findContours функция возвращает два возвращаемых значения, tagetCx и original_image.

Если возвращается None, python не может распространить его среди ваших переменных (targetCx, original_image), поскольку None не может быть повторено. Я не знаю, что находится в возвращаемом значении targetCx, возможно, длина targetCx больше 2.

Предложение
Я думаю, вы хотите получить targetCx и original_image одновременно .
Чтобы добиться этого, вы должны изменить свои коды следующим образом:

# ... code ...
targetCx = None  # Add this line
if contours is not None:
  # ... code ...
  # Remove all return statements inside function body
return targetCx, orig_image  # Change return orig_image to this

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...