Определять правильно переменную, чтобы быть прочитанной во всех частях кода

Хорошие у меня есть этот код и я не осознаю, что я должен перемещать его параметры в функцию ни, которые возвращать.

Он возвращает мне ошибку, которой "grayFrame" он не определен. Я не понимаю, быть ли объявлять это по-другому или в другом месте.

line 41, in buscar_circulos circles = cv2. HoughCircles (grayFrame, cv2. HOUGH_GRADIENT,1,20,param1=50,param2=30,minRadius=0,maxRadius=0) NameError: ямс 'grayFrame' is not defined

Мой код

import numpy as np
import cv2

cap = cv2.VideoCapture(1)

# Función main
def main():

    cv2.namedWindow('ventana')
    cv2.setMouseCallback('ventana',buscar_circulos)

    while(True):

        ret, frame = cap.read()

        grayFrame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        grayFrame = cv2.medianBlur(grayFrame,5)

        cv2.imshow('ventana',grayFrame)

        if cv2.waitKey(1) & 0xFF == ord('q'):
            break

    cap.release()
    cv2.destroyAllWindows()


def buscar_circulos(event,x,y,flags,param):
    if event == cv2.EVENT_LBUTTONDOWN:
        circles = cv2.HoughCircles(grayFrame,cv2.HOUGH_GRADIENT,1,20,param1=50,param2=30,minRadius=0,maxRadius=0)

        if circles is not None:
            circles = np.round(circles[0, :]).astype(int)
            for (x, y, r) in circles:
                cv2.circle(grayFrame, (x, y), r, (255, 0, 0), 1)
                print (x,y)


if __name__ == '__main__':
    main()
0
задан 24.08.2018, 03:11
3 ответа

Для этого, deberГ-схвати использовать глобальные переменные, Г©stas они идут despuГ©s import и могут называться в cГіdigo как будто переменной mГЎs он был, в отличие от которого, чтобы менять ему стоимость, нужно использовать размещенное слово global.

Ты cГіdigo quedarГ - в asГ-:

import numpy as np
import cv2
grayFrame = ""
cap = cv2.VideoCapture(1)

def main():
    global grayFrame #Con esto ya puedes modificar su valor en este método
    cv2.namedWindow('ventana')
    cv2.setMouseCallback('ventana',buscar_circulos)

    while(True):

        ret, frame = cap.read()

        grayFrame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        grayFrame = cv2.medianBlur(grayFrame,5)

        cv2.imshow('ventana',grayFrame)

        if cv2.waitKey(1) & 0xFF == ord('q'):
            break

    cap.release()
    cv2.destroyAllWindows()


def buscar_circulos(event,x,y,flags,param):
    if event == cv2.EVENT_LBUTTONDOWN:
        circles = cv2.HoughCircles(grayFrame,cv2.HOUGH_GRADIENT,1,20,param1=50,param2=30,minRadius=0,maxRadius=0)

    if circles is not None:
        circles = np.round(circles[0, :]).astype(int)
        for (x, y, r) in circles:
            cv2.circle(grayFrame, (x, y), r, (255, 0, 0), 1)
            print (x,y)


if __name__ == '__main__':
    main()

Как хорошо показывает пользователь @Saelyth в комментариях этой publicaciГіn, нужно быть осторожно с глобальными переменными, aquГ - мотив:

https://stackoverflow.com / questions / 19158339/why-are-global-variables-evil

1
ответ дан 20.11.2019, 05:58
  • 1
    Нужно отмечать что, хотя у них есть Ваша утилита, не рекомендует использовать globals, так как он показывает programació n бедняк, который может давать ошибки достаточно problemá костариканские. –  Saelyth 24.08.2018, 03:22
  • 2
    Это не sabí в, ¡ Спасибо! ¿ Qué альтернативы могут использоваться в Вашем месте, которое не подразумевает creació n класса и pará метр self? –  XBoss 24.08.2018, 03:26
  • 3
    Глаз, дело не в том, что esté плохо использовать Globals для scripts así pequeñ вы и проконтролированные вещи. Но если проект начинает делаться каждый раз má s большой, с различными импортируемыми файлами и несколькими человеками работая в этом, использовать globals заканчивает тем, что является ночным кошмаром. Это плохая практика, которая только приходит хорошо " в veces". Брось беглый взгляд в это: stackoverflow.com/questions/19158339/… Поэтому, хотя не esté плохо использовать их как solució n для этого, всегда он заканчивает тем, что предупреждает хорошо xD. –  Saelyth 24.08.2018, 03:33

Другая альтернатива в подсказку @XBoss serГ, - чтобы герметизировать в корпусе все в классе и определять параметр в Вашем "стартапе", этот параметр может быть использованным всеми функциями внутри класса.

import numpy as np
import cv2
cap = cv2.VideoCapture(1)

class MiProgramita(object):
"""Esta clase sirve para [inserta como funciona]"""

    def __init__(self):
        """Define variables que se inicializan a nivel de clase"""
        self.grayframe = ""

    def main(self):
        """Código principal"""
        cv2.namedWindow('ventana')
        cv2.setMouseCallback('ventana',buscar_circulos)

        while(True):

            ret, frame = cap.read()

            self.grayFrame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
            self.grayFrame = cv2.medianBlur(self.grayFrame, 5)

            cv2.imshow('ventana', self.grayFrame)

            if cv2.waitKey(1) & 0xFF == ord('q'):
                break

        cap.release()
        cv2.destroyAllWindows()


    def buscar_circulos(self, event,x,y,flags,param):
        """Función que busca circulos"""
        if event == cv2.EVENT_LBUTTONDOWN:
            circles = cv2.HoughCircles(self.grayFrame,cv2.HOUGH_GRADIENT,1,20,param1=50,param2=30,minRadius=0,maxRadius=0)

        if circles is not None:
            circles = np.round(circles[0, :]).astype(int)
            for (x, y, r) in circles:
                cv2.circle(self.grayFrame, (x, y), r, (255, 0, 0), 1)
                print (x,y)



if __name__ == '__main__':
    ClaseInstanciada = MiProgramita()  # Inicializa la clase
    ClaseInstanciada.main()  # Llama a la función main de la clase.

, В случае когда ты не понимай, поскольку функционирует эта, soluciГіn, tendrГ-схвати, что читать на cГіmo функционируют Class в Пайтоне (Или в programaciГіn ориентируемая на объекты, действительно).

3
ответ дан 20.11.2019, 05:58
  • 1
    Sí это другая solució n. Я это та, которую я обычно использую из-за переменчивости классов, они позволяют делать много má s и считать контролируемыми функции внутри тех же самых. –  XBoss 24.08.2018, 03:43
  • 2
    Точный. Она наиболее практическая долгосрочно. (В меня я costó много, привыкать использовать классы, но смотря в прошлое, это была одна из лучших вещей, которые я смог делать). –  Saelyth 24.08.2018, 03:57
  • 3
    @Saelyth предотвращать глобальные переменные обычно является заданием очень dí ficil, если один - новичок, так как из-за возможности Вашего использования они злоупотребляют ими (я бы никогда это не рекомендовал поэтому +1), этот есть у серьезных incovenientes во время отлаживания, и часто они скрывают другие проблемы, и в существо один новичок не понимает разума, лучшее состоит в том, чтобы герметизировать в корпусе каждый код, и что был indepediente другого. :) –  eyllanesc 24.08.2018, 06:36

Ни существует третья одна vГ - чтобы для это делать без необходимости использовать глобальные переменные ни включать это в классе; переходит с callback vГ - в аргументы все то, в чем он нуждается. Мы можем перемещать словарь с ключом "grayFrame", и который это считал стоимостью array (frame). В существо словарь mutable, мы можем изменять это с обеих функций (в Пайтоне аргументы проходят из-за asignaciГіn). Могут проходить аргументы, которые давайте хотеть используя словарь или другой объект mutable как список, DataClass, и т.д. В C ++ podrГ-хозяева использовать struct, например.

В этот случай setMouseCallback помещает в нашу disposiciГіn аргумент param (userdata в C ++), что существует для этого точно:

import numpy as np
import cv2


# Función main
def main():
    cap = cv2.VideoCapture(1)
    params = {"grayFrame": None}
    cv2.namedWindow('ventana')
    cv2.setMouseCallback('ventana', buscar_circulos, param=params)

    while True:
        ret, frame = cap.read()
        grayFrame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        grayFrame = cv2.medianBlur(grayFrame, 5)
        params["grayFrame"] = grayFrame

        if cv2.waitKey(1) & 0xFF == ord('q'):
            break

        cv2.imshow('ventana', params["grayFrame"])

    cap.release()
    cv2.destroyAllWindows()


def buscar_circulos(event, x, y, flags, param):
    if event == cv2.EVENT_LBUTTONDOWN:
        grayFrame = param["grayFrame"]
        circles = cv2.HoughCircles(grayFrame, cv2.HOUGH_GRADIENT, 1, 20,
                                   param1=50, param2=30, minRadius=0, maxRadius=0
                                   )

        if circles is not None:
            circles = np.round(circles[0, :]).astype(int)
            for x, y, r in circles:
                cv2.circle(grayframe, (x, y), r, (255, 0, 0), 1)
                print(x, y)


if __name__ == '__main__':
    main()

С grayFrame = param["grayFrame"] мы способствуем тому, чтобы переменная grayFrame указала на ссылку объекта, в который он указывает на в этом моменте ключ "grayFrame". Это помимо позволения писать меньше cГіdigo предотвращает ее bГєsqueda в словаре каждый раз, когда мы нуждаемся в стоимости, тем не менее, если мы будем распределять новый объект, нужно делать посредством param["grayFrame"] = obj, если распределяется grayFrame только, изменяется эта локальная переменная, не param["grayFrame"] и следовательно он не влияет на main(). Помнить каждый раз, когда переменные в одиноком Пайтоне отождествляющие снабжает ссылками объект в памяти.

не, если ты cГіdigo оно будет функционировать, как я думаю, что ты ждешь, она detecciГіn только tendrГЎ место в frame (когда кликают) и только dibujarГЎn они cГ-rculos в этом frame в течение мгновения. Если то, что ты хочешь, состоит в том, чтобы включать или дезактивировать ее detecciГіn, когда левша кликать, ты можешь использовать флаг и реализовывать ее detecciГіn mainloop:

import numpy as np
import cv2



def buscar_circulos(event, x, y, flags, param):
    if event == cv2.EVENT_LBUTTONDOWN:
        param["buscar"] = not(param["buscar"])


def main():
    cap = cv2.VideoCapture(0)  # Cambiar dispositivo si procede
    params = {"buscar": False}
    cv2.namedWindow('ventana')
    cv2.setMouseCallback('ventana', buscar_circulos, param=params)

    while True:
        ret, frame = cap.read()
        if params["buscar"]:
            gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
            gray = cv2.GaussianBlur(gray,(9, 9), 2, 2);
            circles = cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, 1, 75,
                                       param1=100, param2=50,
                                       minRadius=0, maxRadius=0
                                       )
            if circles is not None:
                circles = np.round(circles[0, :]).astype("int")
                for (x, y, r) in circles:
                    cv2.circle(frame, (x, y), r, (0, 255, 0), 4)
                    cv2.rectangle(frame, (x - 5, y - 5), (x + 5, y + 5), (0, 128, 255), -1)

        cv2.imshow('ventana', frame)
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break

    cap.release()
    cv2.destroyAllWindows()



if __name__ == "__main__":
    main()

, кликнув в окне, включает ее detecciГіn, вновь кликнув, он дезактивируется и asГ - последовательно. Предварительный фильтр и они parГЎmetros HoughCircles deberГЎn быть отделанными для каждого особенного случая.

2
ответ дан 20.11.2019, 05:58