Подтвердить что ты не робот

DestroyWindow не закрывает окно на Mac с помощью Python и OpenCV

Моя программа создает серию окон, используя следующий код:

def display(img, name, fun):
    global clicked

    cv.NamedWindow(name, 1)
    cv.ShowImage(name, img)
    cv.SetMouseCallback(name, fun, img)

    while cv.WaitKey(33) == -1:
        if clicked == 1:
            clicked = 0
            cv.ShowImage(name, img)

    cv.DestroyWindow(name)

Я нажимаю "q" в окне gui, чтобы закрыть его. Однако код продолжает следующий вызов функции отображения и отображает второе окно gui, не закрывая первое. Я использую Mac с OpenCV 2.1, запуская программу в терминале. Как закрыть окна gui? Спасибо.

4b9b3361

Ответ 1

В графическом интерфейсе OpenCV есть несколько особенностей. В вызове DestroyImage не удается закрыть окно (по крайней мере, в Linux, где бэкендом по умолчанию был Gtk + до 2.1.0), если не было вызвано WaitKey для накачки событий. Добавление вызова WaitKey(1) сразу после DestroyWindow может работать.

Тем не менее, закрытие не гарантируется; функция WaitKey перехвачена только в том случае, если окно имеет фокус, и поэтому, если в окне не было фокуса во время вызова DestroyWindow, скорее всего, он останется видимым до следующего вызова DestroyWindow.

Я предполагаю, что это поведение, которое происходит из Gtk +; функция не вызывала у меня проблем, когда я использовал ее под Windows.

Ответ 2

Вам нужно запустить cv.StartWindowThread() после открытия окна. У меня была такая же проблема, и теперь это работает для меня.

Надеюсь, это поможет будущим читателям. И есть также привязка cv2 (я советую использовать это вместо cv).

Этот код работает для меня:

import cv2 as cv
import time

WINDOW_NAME = "win"

image = cv.imread("ela.jpg", cv.CV_LOAD_IMAGE_COLOR)
cv.namedWindow(WINDOW_NAME, cv.CV_WINDOW_AUTOSIZE)
initialtime = time.time()

cv.startWindowThread()

while (time.time() - initialtime < 5):
  print "in first while"
cv.imshow(WINDOW_NAME, image)
cv.waitKey(1000)

cv.waitKey(1)
cv.destroyAllWindows()
cv.waitKey(1)

initialtime = time.time()
while (time.time() - initialtime < 6):
    print "in second while"

То же самое происходит с версией С++, на Linux: Попытка закрыть окно OpenCV не имеет эффекта

Ответ 3

Sayem2603

Я попробовал ваше решение, и это сработало для меня - спасибо! Я сделал несколько проб и ошибок и обнаружил, что цикл 4 раза помогло... или отправил один и тот же код 4 раза точно так же.

Кроме того, я развернулся до:

cv2.destroyAllWindows()
cv2.waitKey(1)
cv2.waitKey(1)
cv2.waitKey(1)
cv2.waitKey(1)

или просто вызовите DestroyAllWindows, а затем циклически зациклируйте код waitKey() 4 раза:

cv2.destroyAllWindows()
for i in range (1,5):
    cv2.waitKey(1)

Работал также. Я недостаточно сообразителен, чтобы понять, почему это работает точно, хотя я предполагаю, что это имеет какое-то отношение к прерыванию и задержке, созданным путем циклирования этого кода (?)

Маттеус Брандл сказал выше, что третий waitKey() работал на него, поэтому, возможно, он немного отличается от каждой системы? (Я запускаю Linux Mint с ядром 3.16.1 и python 2.7)

Задержка сама по себе не объясняет это, так как простое увеличение времени задержки на waitKey() не делает этого трюка. (Также зацикленную печать ( "Hello" ) 1000 раз вместо использования wiatKey(), чтобы увидеть, помогла ли какая-либо задержка, которая создала, - это не так.) Должно быть, что-то больше связано с тем, как waitKey() взаимодействует с событиями окна.

OpenCV Docs говорят: "Эта функция является единственным методом в HighGUI, который может извлекать и обрабатывать события, поэтому его необходимо периодически вызывать для нормальной обработки событий, если HighGUI не используется в среде, которая занимается обработкой событий."

Возможно, это создает прерывание сортировок в графическом интерфейсе, которое позволяет выполнить действие destroyAllWindows()?

J

Ответ 4

Это решение работает для меня (под Ubuntu 12.04 с открытым python в оболочке):

Повторно вызовите cv.ShowImage после того, как окно "уничтожено".

Ответ 5

Я решил проблему, вызвав cv2.waitKey(1) в цикле for, я не знаю, почему это сработало, но выполняет мою работу, поэтому я больше не беспокоился о себе.

for i in range(1,10):
    cv2.destroyAllWindows()
    cv2.waitkey(1)

вы можете объяснить.

Ответ 6

Если вы используете Spyder (пакет Anaconda), возникает проблема.

Ни один из решений не работал у меня. Я обнаружил, что проблема заключается не в функциях, а в проблеме Spyder. Попытайтесь использовать текстовый редактор плюс, работающий на терминале, и вы будете просто использовать просто:

WINDOW_NAME = "win"
image = cv.imread("foto.jpg", 0)
cv.namedWindow(WINDOW_NAME, cv.CV_WINDOW_AUTOSIZE)

cv.startWindowThread()

cv.imshow(WINDOW_NAME, image)
cv.waitKey()
cv.destroyAllWindows()

Ответ 7

Вот что сработало для меня:

cv2.namedWindow("image")
cv2.imshow('image', img)
cv2.waitKey(0) # close window when a key press is detected
cv2.destroyWindow('image')
cv2.waitKey(1)

Ответ 8

С помощью этой проблемы в консоли python я наблюдал следующее поведение:

  • выдача cv2.imshow после cv2.destroyWindow иногда закрывает окно. Хотя старое окно появляется снова со следующим вызовом highgui, например, cv2.namedWindow
  • третий вызов cv2.waitKey после cv2.destroyWindow закрывал окно каждый раз, когда я пытался. Кроме того, закрытое окно оставалось закрытым даже при использовании cv2.namedWindow after

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

(я использовал Ubuntu 12.10 с python 2.7.3, но OpenCV 2.4.2 из резервных копий 13.04)

Ответ 9

После поиска в течение некоторого времени ни одно из предоставленных решений не работало для меня, так как там была ошибка в этой функции, и у меня не было времени ее исправить, мне не нужно было использовать окно cv2 для отображения фреймов. Как только несколько кадров были сохранены, вы можете открыть файл в другом средстве просмотра, например VLC или MoviePlayer (для Linux).

Вот как я сделал.

 import cv2

 threadDie = True # change this to false elsewhere to stop getting the video
 def getVideo(Message):
          print Message
          print "Opening url"
          video = cv2.VideoCapture("rtsp://username:[email protected]:554/axis-media/media.amp")

          print "Opened url"
          fourcc = cv2.cv.CV_FOURCC('X','V','I','D')
          fps = 25.0 # or 30.0 for a better quality stream
          writer = cv2.VideoWriter('out.avi', fourcc,fps, (640,480),1)
          i = 0

          print "Reading frames "
          while threadDie:
                  ret, img = video.read()
                  print "frame number: ",i
                  i=i+1
                  writer.write(img)
          del(video)


          print "Finished capturing video"

Затем откройте файл с помощью другого средства просмотра, возможно, в более узкой функции, например, если вам нравится vlc, вы можете запустить его и передать сохраненный файл в качестве параметра. На терминале я бы сделал это

vlc out.avi #out.avi is my video file being saved by the function above.

Это сработало для меня в arch linux.

Ответ 10

Кажется, что ни одно из вышеперечисленных решений не сработало для меня, если я запустил его на Jupyter Notebook (окно закрывается при закрытии, и вам нужно принудительно выйти из Python, чтобы закрыть окно).

Я на MacOS High Sierra 10.13.4, Python 3.6.5, OpenCV 3.4.1.

Приведенный ниже код работает, если вы запускаете его как файл.py (источник: https://www.learnopencv.com/read-write-and-display-a-video-using-opencv-cpp-python/). Он открывает камеру, записывает видео, успешно закрывает окно после нажатия клавиши "q" и сохраняет видео в формате.avi.

import cv2
import numpy as np

# Create a VideoCapture object
cap = cv2.VideoCapture(0)

# Check if camera opened successfully
if (cap.isOpened() == False): 
  print("Unable to read camera feed")

# Default resolutions of the frame are obtained.The default resolutions are system dependent.
# We convert the resolutions from float to integer.
frame_width = int(cap.get(3))
frame_height = int(cap.get(4))

# Define the codec and create VideoWriter object.The output is stored in 'outpy.avi' file.
out = cv2.VideoWriter('outpy.avi',cv2.VideoWriter_fourcc('M','J','P','G'), 10, (frame_width,frame_height))

while(True):
  ret, frame = cap.read()

  if ret == True: 

    # Write the frame into the file 'output.avi'
    out.write(frame)

    # Display the resulting frame    
    cv2.imshow('frame',frame)

    # Press Q on keyboard to stop recording
    if cv2.waitKey(1) & 0xFF == ord('q'):
      break

  # Break the loop
  else:
    break 

# When everything done, release the video capture and video write objects
cap.release()
out.release()

# Closes all the frames
cv2.destroyAllWindows() 

Ответ 11

Это работает для меня в Spyder:

import cv2 as cv
cv.namedWindow("image")
img = cv.imread("image_name.jpg")
cv.imshow("image",img)

cv.waitKey(5000) # 5 sec delay before image window closes
cv.destroyWindow("image")

Не забудьте использовать только cv.waitKey(positive Integer) чтобы это работало