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? Спасибо.
Ответы
Ответ 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)
чтобы это работало