SR2D и веб-камера (VB6). Удалось!

Работа с 2D и 3D графикой, видео, звуком.

Модератор: Mikle

С.Т.
Обычный пользователь
Обычный пользователь
 
Сообщения: 50
Зарегистрирован: 10.03.2010 (Ср) 19:49

SR2D и веб-камера (VB6). Удалось!

Сообщение С.Т. » 26.04.2025 (Сб) 11:39

(ПРАВКА: Последняя тестовая версия как минимум здесь)

В приложении - тестовый проект, который передаёт видео-поток с Веб-камеры на SR2D-спрайт для дальнейших неограниченных преобразований (не только цвета и наложения; Sprite.GetPixel позволит даже управлять программой через камеру и распознавать видео вроде OCR в реальном времени). Может, кому-то будет полезно.

Камера воплощена через некое TesoSeeu.ocx, это единственный движок камеры, который у меня заработал сразу и со всеми камерами и без малейших недостатков (хотя к VB6 он не приспособлен и лёг на неё чисто случайно). Но он рисует изображение только на себе и не умеет выводить картинку, а может лишь фотографировать в сырой буфер памяти. Процедуру вывода изображения из оперативки в stream и затем на спрайт я уже подобрал сам; наверняка код требует поправок, которые приветствуются (например, две CopyMemory на кадр, возможно, излишни), но я остановился на рабочем варианте и особо оптимизировать не пытался.

В остальных случаях, насколько мне удавалось изучить, веб-камера с VB6 плохо дружит.
Было два варианта подключения:
1) старый - capCreateCaptureWindow (ненадёжный, зачастую выдаёт пустой экран вместо камеры, а если и включается - всегда тянет, изображение меняется ступенчато; к тому же, при каждом подключении выдаёт неубиваемое окно выбора камеры, которое захлопнуть мне удалось только сторонне запущенным скриптом AHK, т.к. программка VB с WM_CLOSE или SendKeys закрывает его как-то не так, как нужно для корректной работы камеры, а WM_QUIT закрывает вместе с окном самой программы) -
2) и новый, DirectShow (но он плохо совместим c VB6 и сложный, все "готовые" разработки в сети я проверил, и они не работают, к тому же там ручной выбор камеры, среди камер много мусора и т.д.).
Были в интернете и различные вебкамерные OCX специально для VB6 с готовыми проектами, но у меня хорошо не заработал НИ ОДИН из них (кроме WebCamX, но тот вообще не имеет вывода кроме как в файл).
А этот работает чётко, см. вложение.
У вас нет доступа для просмотра вложений в этом сообщении.
Последний раз редактировалось С.Т. 01.08.2025 (Пт) 11:47, всего редактировалось 28 раз(а).

Mikle
Изобретатель велосипедов
Изобретатель велосипедов
Аватара пользователя
 
Сообщения: 4163
Зарегистрирован: 25.03.2003 (Вт) 14:02
Откуда: Туапсе

Re: SR2D и веб-камера (VB6). Удалось!

Сообщение Mikle » 26.04.2025 (Сб) 18:59

Круто! Работает.

С.Т.
Обычный пользователь
Обычный пользователь
 
Сообщения: 50
Зарегистрирован: 10.03.2010 (Ср) 19:49

Re: SR2D и веб-камера (VB6). Удалось!

Сообщение С.Т. » 18.06.2025 (Ср) 19:37

А гораздо лучше работает новый вариант - с двумя потоками (через vbCreateThread от TheTrick).

Ибо пока он читал новый кадр из камеры (а в темноте у неё выдержка до полусекунды!), программа торчала на месте.
А теперь - смотрите: кадр висит один и тот же (пока-а-а он там новый кадр назначит), а главный поток занимается вращением спрайта, за счёт чего вращение происходит более гладко. А когда я и масштабирование спрайта перенёс туда же в поток, где считывание кадра, а главному потоку осталось лишь наложить два готовых спрайта с вращением, он стал крутиться вообще гладко-гладко и на мышь откликаться мгновенно:

Веб-камера в отдельном потоке.zip


При запуске выбираем вариант: полноценные ДВА потока либо ОДИН (по Таймеру с формы). Разница ошеломительна! (200 FPS против 20 в нормальных условиях, в темноте ещё разительней.)

Кстати, тут двухпоточность реализована без маршалинга, а с ручным экранированием общих Public-переменных от одновременного обращения из двух потоков. Мне даже кажется это допустимым для элементарных задач (в моём случае в отдельном потоке всегда будет только один цикл на несколько строчек, сколь бы ни усложнялся основной проект). Знаю, что это наивная глупость, но ведь работает быстро и вроде стабильно...

Воплощено это так. Пока побочный поток пишет новый спрайт, главный поток считывает его прошлую версию. Для этого общий спрайт реализован в виде не просто переменной, а Public-массива с двумя индексами: -1 и 0, и индивидуального номера рабочего индекса. Пока читаем Sprite(nSprite), пишем в Sprite(Not nSprite), а по окончании записи переключаем рабочий номер: nSprite = Not nSprite, и вот уже читать в главном потоке будем обновлённый спрайт, пока побочный поток пишет в нерабочий спрайт. Вот так, меняя их местами, мы обеспечиваем изоляцию элементов массива от чтения из другого потока. При том что сам массив для обоих потоков общий, видимый отовсюду, и к тому же второй поток обращается напрямую к Webcam-контролу вызвавшей его формы из первого потока (!) и ко всем глобальным переменным, но поскольку явных обращений к Webcam-контролу из главного потока не происходит НИКОГДА и одновременного обращения к Public-переменным не происходит НИКОГДА (гарантированно), слётов и глюков пока не наблюдается. А если и слетит один раз из тысячи, это всё равно лучше, чем пихать обработку кадров с камеры в общий поток и ВСЕГДА наблюдать пьяную ступенчатую картинку.

Прочитав дискуссию Хакера с The Trick в теме "Многопоточность - часть 4", я подумал: раз уж по-настоящему великие программисты не находят идеального подхода для StandardExe, то бог с ним, работает ведь - и ладно. Все API побочного потока объявлены локально в его модуле (интуиции кажется это более безопасным), встроенная функция Timer вставлена в поток лишь для пробы, она не нужна. Всё, что должен делать поток - снять карточку, обработать и выдать спрайт. И сколь бы ни усложнялся основной проект, отдельного потока это почти не коснётся, и свято блюсти его изоляцию не представляет труда. Вероятно, хитрости с подменой заголовка и т.д. в modMultiThreading действительно делают такой наивный подход возможным!
У вас нет доступа для просмотра вложений в этом сообщении.

Vova_2581
Постоялец
Постоялец
 
Сообщения: 391
Зарегистрирован: 10.01.2010 (Вс) 18:08

Re: SR2D и веб-камера (VB6). Удалось!

Сообщение Vova_2581 » 21.06.2025 (Сб) 18:01

По web-камере когда-то давно делал, есть тут на форуме и такого...
1) старый - capCreateCaptureWindow (ненадёжный, зачастую выдаёт пустой экран вместо камеры, а если и включается - всегда тянет, изображение меняется ступенчато; к тому же, при каждом подключении выдаёт неубиваемое окно выбора камеры, которое захлопнуть мне удалось только сторонне запущенным скриптом AHK, т.к. программка VB с WM_CLOSE или SendKeys закрывает его как-то не так, как нужно для корректной работы камеры, а WM_QUIT закрывает вместе с окном самой программы)

Не наблюдается так чтобы ну совсем всё плохо. Там и отдельные потоки и закрывается все нормально и вопрос с "пустым экраном" тоже решен. Я и сам до сих пор пользуюсь этой прогой на работе для проверки работы разных камер на 7 и 10 win всё нормально работает и во многом зависит от настроек. Разве что со "ступенчатым изображением" может быть да... есть немного. Ну это мелочи.

С.Т.
Обычный пользователь
Обычный пользователь
 
Сообщения: 50
Зарегистрирован: 10.03.2010 (Ср) 19:49

Re: SR2D и веб-камера (VB6). Удалось!

Сообщение С.Т. » 22.06.2025 (Вс) 4:47

...
Последний раз редактировалось С.Т. 25.06.2025 (Ср) 16:17, всего редактировалось 1 раз.

С.Т.
Обычный пользователь
Обычный пользователь
 
Сообщения: 50
Зарегистрирован: 10.03.2010 (Ср) 19:49

Re: SR2D и веб-камера (VB6). Удалось!

Сообщение С.Т. » 22.06.2025 (Вс) 4:48

...
Последний раз редактировалось С.Т. 25.06.2025 (Ср) 16:18, всего редактировалось 1 раз.

С.Т.
Обычный пользователь
Обычный пользователь
 
Сообщения: 50
Зарегистрирован: 10.03.2010 (Ср) 19:49

Re: SR2D и веб-камера (VB6). Удалось!

Сообщение С.Т. » 22.06.2025 (Вс) 9:47

...
Последний раз редактировалось С.Т. 25.06.2025 (Ср) 16:19, всего редактировалось 1 раз.

С.Т.
Обычный пользователь
Обычный пользователь
 
Сообщения: 50
Зарегистрирован: 10.03.2010 (Ср) 19:49

Re: SR2D и веб-камера (VB6). Удалось!

Сообщение С.Т. » 22.06.2025 (Вс) 9:50

...
Последний раз редактировалось С.Т. 25.06.2025 (Ср) 16:18, всего редактировалось 1 раз.

С.Т.
Обычный пользователь
Обычный пользователь
 
Сообщения: 50
Зарегистрирован: 10.03.2010 (Ср) 19:49

Re: SR2D и веб-камера (VB6). Удалось!

Сообщение С.Т. » 22.06.2025 (Вс) 10:04

...
Последний раз редактировалось С.Т. 25.06.2025 (Ср) 16:18, всего редактировалось 1 раз.

С.Т.
Обычный пользователь
Обычный пользователь
 
Сообщения: 50
Зарегистрирован: 10.03.2010 (Ср) 19:49

Re: SR2D и веб-камера (VB6). Удалось!

Сообщение С.Т. » 22.06.2025 (Вс) 19:41

Если речь про это, то разумеется я опробовал еще много лет назад. У меня не работает, как и ни один на основе capCreateCaptureWindow. Windows запрашивает камеру, это окно надо как-то убить, тогда раз через раз какая-то камера включается, на втором запуске всегда стабильно чёрный экран...

А TesoSeeu работает всегда и на любых компьютерах, сам выбираешь камеру, изображение отличное.
Но я его недооценил! Я снимал изображение через Cam.SnapOne, а оно тормозит программу на выдержку камеры.
НО У НЕГО ЕСТЬ EVENT на форму!
А включается он, если при OpenCapDev указать вторым параметром 1.

Тогда каждый кадр вызывает Cam_EventOfCamera АСИНХРОННО! Остальное время форма работает, и (условное) вращение будет происходить ПЛАВНО! И многопоточность НЕ НУЖНА!
Путём проб и ошибок нашёл, как выцепить изображение по указателю, который он присылает:

Код: Выделить всё
'Каждый новый кадр камеры вызывает:
    Private Sub Cam_EventOfCamera(ByVal pBmp As Long, ByVal nTyp As Long)
        size& = Cam.GetImgLen(1)
        hData& = GlobalAlloc(2&, size)
        pData& = GlobalLock(hData)
        CopyMemory ByVal pData, ByVal pBmp, size
        GlobalUnlock hData
        SprBack.LoadFromData hData ' Метод LoadFromData добавил на основе LoadFromBytes с форума Arthur02   http://bbs.vbstreets.ru/viewtopic.php?f=6&t=56557
        SprBack.PaintToDevice hDC
    End Sub


Обновил проект-болванку на чистовик, теперь на его основе можно писать программы для веб-камеры. В моём случае камера работает на 6 FPS, а форма – на 28 FPS (обрабатывая многократно один и тот же кадр камеры). Тестовые счётчики при отключённой камере НЕ МЕНЯЮТ СКОРОСТИ, т.е. работа камеры нисколько не нагружает форму (как видим, задержка возникает лишь в момент открытия камеры):
VB6 Веб-Камера по событию, без задержки.zip

(ДАЛЬНЕЙШЕЕ ДОБАВЛЕНИЕ: Всё работало хорошо, а однажды вдруг начал часто зависать при закрытии камеры, открытой через "OpenCapDev 1". Вероятно, эта команда создаёт поток, а VB этого не любит, и при определенном расположении данных в памяти такой вариант становится плох (тот же самый EXE!).
Для надёжности нужно открывать нужно только через OpenCapDev 0, но тогда не работает callback-функция EventOfCamera, и снимки придётся делать всё-таки через vbCreateThread. Эта функция в свою очередь не дружит с модулем Bass.dll, который тоже многопоточен, и, возможно, и с другими вариантами воспроизведения аудио (не проверял, в своей программе просто вынес Bass в отдельный процесс).
В общем, данное вложение не рекомендую, пользуйтесь двумя первыми вариантами.)
У вас нет доступа для просмотра вложений в этом сообщении.
Последний раз редактировалось С.Т. 07.07.2025 (Пн) 19:19, всего редактировалось 3 раз(а).

Vova_2581
Постоялец
Постоялец
 
Сообщения: 391
Зарегистрирован: 10.01.2010 (Вс) 18:08

Re: SR2D и веб-камера (VB6). Удалось!

Сообщение Vova_2581 » 24.06.2025 (Вт) 13:03

Ого! Зачем так много повторений? :shock:

Vova_2581
Постоялец
Постоялец
 
Сообщения: 391
Зарегистрирован: 10.01.2010 (Вс) 18:08

Re: SR2D и веб-камера (VB6). Удалось!

Сообщение Vova_2581 » 24.06.2025 (Вт) 14:13

Что-то не то вы делаете. Если в системе одна камера, то никакого запроса... не будет. "Черный экран" зависит от метода сжатия, оно меняется в настройках. Как я уже сказал: у меня с capCreateCaptureWindow нет никаких особых проблем, всё работает нормально, ну вы конечно в праве выбирать, что вам удобней то и используйте. :wink:

Vova_2581
Постоялец
Постоялец
 
Сообщения: 391
Зарегистрирован: 10.01.2010 (Вс) 18:08

Re: SR2D и веб-камера (VB6). Удалось!

Сообщение Vova_2581 » 24.06.2025 (Вт) 18:38

Посмотрел ваш проект по ссылке... ну или не ваш, но вами переделаный, не важно...
Что могу сказать: очень излишне сложно все закручено. Там и ActiveX... и dll дополнительно и классы в проекте - целая ГОРА(!) кода. Ахренеть!!! :shock: Зачем это все??? Так много лишнего... устал считать сколько там деклараций на 974 сбивался и снова считал, потом бросил, устал! Ну его... :cry:
С API capCreateCaptureWindow в 100 тыщ миллионов раз проще! Код простой и его немного совсем, для детей написанный. Может без спецэффектов... но по качеству картинки все тоже самое. Я, кстати, свой код на разных камерах пробовал на работе нет проблем все отлично работает! :D Все окна настроек с выбором камер (если их несколько) не нужно закрывать через "перезагрузку системы", ничего не зависает, все элементы управления окна доступны, если установить параметр fYield = true нет проблем! Темный экран... возможно, нужно просто изменить в "Формат видео" параметр "Глубина цвета (бит) и сжатие" с MJPEG (не все камеры поддерживают) на YUY2 и все работает! Ну, в общем, это ваше дело, конечно, что лучше лично для вас, но на мой личный взгяд: всегда лучше "гору" обойти, чем карабкаться на нее в поте лица своего. В прочем... как угодно, это ваше личное дело, вам и решать. Хорошего дня! :)

С.Т.
Обычный пользователь
Обычный пользователь
 
Сообщения: 50
Зарегистрирован: 10.03.2010 (Ср) 19:49

Re: SR2D и веб-камера (VB6). Удалось!

Сообщение С.Т. » 25.06.2025 (Ср) 16:36

(Повторения убрал, извиняюсь, не отправлялось, потом через несколько дней сразу всё прилетело.)

Поясню насчёт моего сдвоенного проекта - он посвящен не камере, а движку SR2D от Mikle, который и занимает большую часть проекта, включая DLL. Задача проекта не отобразить картинку, а вывести её в движении на СПРАЙТ. Для чего? Для дальнейших преобразований картинки, когда они именно требуются, и внедрения "видеопотока" в основную 2D-программу. Так тема и называется: Вывод камеры на SR2D. В этом и были некоторые сложности, которые разрешены и проект готов к заполнению. Кстати, код только в форме (содержит тестовую часть, подлежащую удалению), всё остальное - движок.

А если нужен ПРОСТО вывод картинки с вебкамеры на экран, то проект занимает 14 строк кода:
У вас нет доступа для просмотра вложений в этом сообщении.
Последний раз редактировалось С.Т. 25.06.2025 (Ср) 17:31, всего редактировалось 5 раз(а).

С.Т.
Обычный пользователь
Обычный пользователь
 
Сообщения: 50
Зарегистрирован: 10.03.2010 (Ср) 19:49

Re: SR2D и веб-камера (VB6). Удалось!

Сообщение С.Т. » 25.06.2025 (Ср) 16:48

Эти 14 строк посвящены выбору действующей камеры из списка подключённых камер, но даже они не обязательны. Достаточно такого кода:
Код: Выделить всё
Private Sub Form_Load()
    Cam.OpenCapDev 0, 0
End Sub

И присоединить OCX, даже не подлежащий регистрации. Программа откроет камеру, если она есть, и выведет изображение на экран.

Но бывают случаи, когда с изображением с камеры нужно что-то делать. Не просто эффекты, не просто замена фона, сдвижение и т.д., а ещё и участие картинки в сути самой программы, и это не обязательно изображение лица. В моем случае камера должна считывать движения рук, в другом случае РАСПОЗНАВАТЬ клавиши, схваченные камерой, белый цвет класть на фон цветовых линий и т.д. - всё это довольно сложный проект на стыке психологии, педагогики и музыки. Есть и другие случаи. Схваченное таким образом изображение можно даже РАСПОЗНАВАТЬ путём проверки пикселей (в SR2D команда GetPixel), и компьютер может на ходу определять, ЧТО он видит и ГДЕ, на ходу менять масштаб и положение камеры программно для отображения картинки на тех объектах, которые задуманы, и т.д. Всё это делается довольно легко на основе проекта из этой темы (не из последнего поста, разумеется).

А просто отобразить картинку на форме или записать в файл - такой задачи передо мной не стояло... Но найдя, как надёжно и МАКСИМАЛЬНО просто подружить камеру именно с ДВИЖКОМ SR2D (на котором основан остальной мой проект), я выложил это решение для тех, кто может использовать это по-своему.
Последний раз редактировалось С.Т. 25.06.2025 (Ср) 17:16, всего редактировалось 2 раз(а).

С.Т.
Обычный пользователь
Обычный пользователь
 
Сообщения: 50
Зарегистрирован: 10.03.2010 (Ср) 19:49

Re: SR2D и веб-камера (VB6). Удалось!

Сообщение С.Т. » 25.06.2025 (Ср) 17:04

Раз уж на то пошло:
Vova_2581 писал(а):Что-то не то вы делаете. Если в системе одна камера, то никакого запроса... не будет. "Черный экран" зависит от метода сжатия, оно меняется в настройках.

У меня одна камера (встроенная на ноутбуке), но при запуске Web-camera monitor (версия 1.1.14) сперва появляется штатный виндоусный диалог выбора камеры, затем (независимо от выбора) появляется окно с чёрным экраном, на кнопку "Выбрать видеоустройство" не реагирует, "Установить формат" не реагирует, "Выбрать формат" показывает 5 вариантов (а откуда я знаю, какой формат у моей камеры?) и при выборе любого из них пишет "Видеоустройство не поддерживает выбранное разрешение!". Дальше разбираться не стал. Подключение USB-камеры ничего не меняет. Windows 7 x64, запуск как из IDE, так и скомпилированного файла. Несколько лет назад в этой проге удавалось как-то через раз получить картинку, сейчас ни разу.
Поэтому я продолжил поиски и нашёл через тонны материала на каком-то заброшенном китайском иероглифическом сайте OCX, который вдруг чудесным образом заработал на VB6 и работает с одной строчки! Удалось (не без ухищрений с оперативкой) и положить её живую картинку на 2D-графику для обработки, что в моём случае критически важно. Вот этой последней находкой я и решил поделиться.

Vova_2581
Постоялец
Постоялец
 
Сообщения: 391
Зарегистрирован: 10.01.2010 (Вс) 18:08

Re: SR2D и веб-камера (VB6). Удалось!

Сообщение Vova_2581 » 25.06.2025 (Ср) 17:30

Ок. SR2D это ваша специфика, понятно.
Насчёт последнего поста... Странно... Мне уже и самому интересно... Давайте немного позже вам напишу, по свободе один вариант попробуем, если вы не против.

С.Т.
Обычный пользователь
Обычный пользователь
 
Сообщения: 50
Зарегистрирован: 10.03.2010 (Ср) 19:49

Re: SR2D и веб-камера (VB6). Удалось!

Сообщение С.Т. » 25.06.2025 (Ср) 17:34

Хорошо. Но лучше не здесь, а в вашей теме, ладно?

Vova_2581
Постоялец
Постоялец
 
Сообщения: 391
Зарегистрирован: 10.01.2010 (Вс) 18:08

Re: SR2D и веб-камера (VB6). Удалось!

Сообщение Vova_2581 » 25.06.2025 (Ср) 21:04

Да, хорошо, без проблем.

С.Т.
Обычный пользователь
Обычный пользователь
 
Сообщения: 50
Зарегистрирован: 10.03.2010 (Ср) 19:49

Re: SR2D и веб-камера (VB6). Удалось!

Сообщение С.Т. » 25.07.2025 (Пт) 12:13

И ещё один вариант многопоточной обработки видеосигнала с веб-камеры.
VbCreateThread превосходно справляется, но если подключить сторонние DLL со своей многопоточностью (например, BASS.dll для работы звуком и подключения к MIDI), программа начинает падать. Подружить их какими-то финтами удаётся, но надёжным это не выглядит.
Выход найден в использовании ВСТРОЕННОЙ МНОГОПОТОЧНОСТИ VB6, которую все ругают, а я не выявил в ней ни одного недостатка, если использовать многопоточность по назначению. Проект разместил в другой теме, в нём пятый пример - снимки камеры с увеличением на весь экран (одно увеличение занимает 100 мс на кадр, о снимках и не говорю) выведены в отдельный поток, форма свободна и может делать с этим "видео" что угодно:
viewtopic.php?f=15&t=39686&p=6796322#p6796322

The trick
Постоялец
Постоялец
 
Сообщения: 808
Зарегистрирован: 26.06.2010 (Сб) 23:08

Re: SR2D и веб-камера (VB6). Удалось!

Сообщение The trick » 25.07.2025 (Пт) 16:37

С.Т. писал(а):VbCreateThread превосходно справляется, но если подключить сторонние DLL со своей многопоточностью (например, BASS.dll для работы звуком и подключения к MIDI), программа начинает падать.

Не. Так делать не стоит. Если у тебя могут быть вызовы из произвольных потоков - то нужно делать маршалинг. В модуле есть готовые функции для маршалинга.

Я глянул твой пример - там у тебя при вызове MainForm.НовыйКадр в ThreadForm_LoopAction, один поток засыпает и переключается на основной поток - тем самым программа превращается в этом месте в однопоточную. К примеру если основной поток в этот момент будет занят - все потоки будут ждать. Чтобы передавать приватные объекты между апараментами смотри у меня в модуле функцию EnablePrivateMarshaling.
UA6527P

The trick
Постоялец
Постоялец
 
Сообщения: 808
Зарегистрирован: 26.06.2010 (Сб) 23:08

Re: SR2D и веб-камера (VB6). Удалось!

Сообщение The trick » 25.07.2025 (Пт) 16:45

Если тебе необходимо сделать чтобы в потоке просто получалось изображение с "тормознутой" камеры (сам почти никогда не имел дело с камерами мб там есть асинхронные механизмы), то синхронизация вообще не нужна. Какая разница если выведется на экран половина прошлого кадра и половина нового изредка? Просто создавай буфер под картинку и в отдельном потоке пиши в него, а в другом читай - и все! Если уж прямо важно качество в этом плане - то можно через SRW локи или критические секции залочить запись в общий буфер.
UA6527P

С.Т.
Обычный пользователь
Обычный пользователь
 
Сообщения: 50
Зарегистрирован: 10.03.2010 (Ср) 19:49

Re: SR2D и веб-камера (VB6). Удалось!

Сообщение С.Т. » 25.07.2025 (Пт) 21:36

The trick писал(а):Если тебе необходимо сделать чтобы в потоке просто получалось изображение с "тормознутой" камеры (сам почти никогда не имел дело с камерами мб там есть асинхронные механизмы),

Есть, и в нашем OCX камеры можно её открыть асинхронным образом (с параметром 1) и получать кадры на форму как события. Но тогда при закрытии камеры (не всякой) программа зависает. Не дружен этот механизм с VB6, видать. Синхронные же кадры вызывают ступенчатость формы даже на хорошей камере, т.к. обработка изображений тоже занимает время. Отключаешь съём кадра или выносишь в отдельный поток - форма сразу становится плавной.
то синхронизация вообще не нужна. Какая разница если выведется на экран половина прошлого кадра и половина нового изредка?


Так это даже лучше, если полкадра нового - меньше запаздывание картинки! Но я пробовал напрямую писать и читать; тогда кадр то и дело засвечивается, как под электросваркой, и вскоре программа падает. Это из-за того, что нет маршалинга? Маршалинг это исправит? (пока не сумел его наладить)
Всё-таки мы имеем дело с передачей объекта класса, а не просто картинки. А хотя! Теперь понял! А что если передавать в другой поток не класс, а непосредственно массив картинки? А в класс её запихивать уже в новом потоке. Тогда массив может переписаться с середины и будет валидным!

The trick писал(а):Просто создавай буфер под картинку и в отдельном потоке пиши в него, а в другом читай - и все!

А что такое буфер под картинку?
Алгоритм таков: картинка из камеры поступает в виде указателя на стрим типа IUnknown. Потом мы высекаем из этого стрима через CopyMemory другой указатель - уже на данные. Потом выцепляем эти данные через еще один CopyMemory сразу в класс SR2D, а можно вместо этого сразу в массив изображения. Как лучше: в класс или в массив? А потом в основном потоке считываем это изображение (в каком формате - не важно, момент перехода в другой поток можно ввести на любом этапе преобразований) и отображаем в модифицированном виде на форме.
Последний раз редактировалось С.Т. 25.07.2025 (Пт) 23:40, всего редактировалось 7 раз(а).

С.Т.
Обычный пользователь
Обычный пользователь
 
Сообщения: 50
Зарегистрирован: 10.03.2010 (Ср) 19:49

Re: SR2D и веб-камера (VB6). Удалось!

Сообщение С.Т. » 25.07.2025 (Пт) 21:53

The trick писал(а): Я глянул твой пример - там у тебя при вызове MainForm.НовыйКадр в ThreadForm_LoopAction, один поток засыпает и переключается на основной поток - тем самым программа превращается в этом месте в однопоточную. К примеру если основной поток в этот момент будет занят - все потоки будут ждать.

Да, я знаю... и то же самое при спускании нового кадра через Event... Но если основной поток занят, то он и не сможет отобразить результата, и в таком случае задержка с поставкой материала будет почти незаметна. В этом, наверно, и была логика создателей VB. Да и негоже мне грузить основной поток при наличии многопоточности. У меня поток формы в основном занимается отрисовкой (по таймеру с Interval=1, получается примерно 20 раз в секунду) и надолго не залипает. Хотя некоторое дополнительное отставание на кадр-другой конечно будет наблюдаться, потому что поток камеры работает не в полную силу, а с микроожиданиями, во время коих отобразится старый кадр. Вот и думаю, какой же вариант поточности выбрать за основу для дальнейшей работы, чтоб уже не переделывать.

Если у тебя могут быть вызовы из произвольных потоков - то нужно делать маршалинг.

Не совсем понял: вызовы чего? Переменных? - только в одну сторону. А вызовов процедур между потоками вообще нет, за исключением процесса настройки камеры (но настройку я вообще сводил в один поток для надёжности). Задача созданного потока только одна: циклически обновлять общую переменную "Кадр". Хотя изначально это даже не переменная, а указатель (в таком виде поставляет его камера). Указатель я сперва материализую (но ведь это необходимо?), он становится объектом класса, а потом уже обращаться к этому объекту из другого потока. Созданный поток только однажды считывает настройки камеры из общих переменных, а дальше не принимает ни переменных, ни вызовов процедур, а только обновляет кадр. И ещё: теперь подумалось: а если основной поток будет читать картинку из побочного именно по сырому указателю на данные, ещё до CopyMemory? И пусть он указывает на половину старой картинки и половину новой. (Интуитивно кажется, что это далеко не лучший выбор, т.к. через миг он может указывать чёрти-куда.)

Но гораздо большая проблема в том, что сам факт запуска modMultiThreading.Initialize и запуска BASS_Init вместе приводит к очень плохим результатам, которые мне как-то удалось примирить, через отсрочки по таймерам, определенную последовательность закрытий и т.д., но как-то скорей методом тыка, и не факт, что на другом компьютере всё не завалится.

С.Т.
Обычный пользователь
Обычный пользователь
 
Сообщения: 50
Зарегистрирован: 10.03.2010 (Ср) 19:49

Re: SR2D и веб-камера (VB6). Удалось!

Сообщение С.Т. » 27.07.2025 (Вс) 14:30

А можно задать вопрос профессионалам? (Привык сам всё находить, но тут слишком уж не владею теорией.)

В моём случае кадр с OCX получилось брать только следующим образом:

Код: Выделить всё


'1) Получаем кадр с OCX "Cam" в чёрти-каком формате указателя:
                 Dim Buf As Long, Size As Long
    Buf = Cam.SnapOne(1&)
    Size = Cam.GetImgLen(1&):    If Size = 0 Then Exit Function

'2) ВЫВОДИМ ЭТОТ КАДР В ОПЕРАТИВКУ:
               Dim hData As Long, pData As Long
    hData = GlobalAlloc(2&, Size)
    pData = GlobalLock(hData)
    CopyMemory Destination:=ByVal pData, Source:=ByVal Buf, Size:=Size
    GlobalUnlock hData
    'Теперь hData содержит опять же указатель на сырой кадр камеры.
    '(Без GlobalLock тоже работает, но говорят, так безопасней.)

'3) ВЫВОДИМ ЕГО В СТРИМ:
                              Dim Stream  As IUnknown
                           
                              Dim tSI As GdiplusStartupInput
                              Dim GDIP As Long
                              Dim Bmp As Long
                              Dim lData As BitmapData

    tSI.GdiplusVersion = 1
    If GdiplusStartup(GDIP, tSI) = 0 Then 'если удалось запустить GDI+,
   
      CreateStreamOnHGlobal hData, 1&, Stream 'создаём стрим
     
'4) ВЫЦЕПЛЯЕМ ИЗ СТРИМА изображение в формат BMP:
               Dim R As RECTL
               Dim x As Long, y As Long
               Dim cBuf() As Long  'массив, в который положим физический КАДР наконец-то!
                             
      If GdipLoadImageFromStream(Stream, Bmp) = 0 Then 'Если удалось,
        'Смотрим размеры:
            GdipGetImageWidth Bmp, x
            GdipGetImageHeight Bmp, y
            R.Left = 0:  R.Right = x
            R.Top = 0:  R.Bottom = y
        If GdipBitmapLockBits(Bmp, R, ImageLockModeRead, PixelFormat32bppARGB, lData) = 0 Then
          ReDim cBuf(x * y - 1) 'готовим массив для изображения кадра
          lData.Width = lData.Width - 20
          CopyMemory Destination:=cBuf(0), Source:=ByVal lData.Scan0, Size:=x * y * 4
          'Наконец-то получили изображение в массив cBuf() !
          GdipBitmapUnlockBits Bmp, lData
        End If
        GdipDisposeImage Bmp
      End If
      Set Stream = Nothing
      GdiplusShutdown GDIP
    End If




Только по такому алгоритму получается получать кадры с камеры.
Но:

1. Нельзя ли получать кадр проще: без двух CopyMemory, без древней GlobalAlloc, без запуска и остановки GDI+ для каждого кадра? Можно ли, к примеру, один раз запустить стрим и не перезапускать его для каждого кадра? (Сразу оговорюсь: я не понимаю, что такое стрим, и не разбираюсь в оперативке, а код этот слепил методом тыка на основе разных источников.)

2. (самое главное) Массив с конечным кадром cBuf() всякий раз ложится в разные адреса (в том смысле что VarPtr(cBuf(0)) меняется, хотя не стихийно, часто повторяет несколько адресов). Вопрос: Можно ли сделать так, чтобы этот cBuf() лежал ВСЕГДА ПО ОДНОМУ АДРЕСУ, чтобы указатель не менялся и чтобы можно было прочитать из этого адреса в любой момент, к примеру через полсекунды? Ведь размер массива всегда одинаковый (равен разрешению камеры).

Поясню, для чего это нужно. В режиме штатной многопоточности ActiveX EXE кадры прекрасно передаются по указателю в другой поток. Я не оговорился: по VarPtr(cBuf(0)) и W*H*4 в другой поток, который находится (как говорят) в другом адресном пространстве, т.к. это новая копия класса по CreatrObject при "Thread per Object". Но указатель на cBuf() плавает, и потому ежели чтение происходит не тотчас, а через какое-то время (через дополнительный общий класс), то CopyMemory рушит программу. Можно ли зафиксировать этот указатель, чтобы cBuf() всегда находился по одному адресу, и читать его можно было в любое время?
Последний раз редактировалось С.Т. 27.07.2025 (Вс) 14:50, всего редактировалось 3 раз(а).

The trick
Постоялец
Постоялец
 
Сообщения: 808
Зарегистрирован: 26.06.2010 (Сб) 23:08

Re: SR2D и веб-камера (VB6). Удалось!

Сообщение The trick » 27.07.2025 (Вс) 14:33

С.Т. писал(а):Но гораздо большая проблема в том, что сам факт запуска modMultiThreading.Initialize и запуска BASS_Init вместе приводит к очень плохим результатам

Нужно смотреть в чем дело. Про маршалинг я имел в виду, если у тебя какие-либо колбеки идут от Bass.dll то там возможно они из разных потоков поступают. В модуле есть спец механизм для этого.
UA6527P

The trick
Постоялец
Постоялец
 
Сообщения: 808
Зарегистрирован: 26.06.2010 (Сб) 23:08

Re: SR2D и веб-камера (VB6). Удалось!

Сообщение The trick » 27.07.2025 (Вс) 14:35

Почему-то не прикрепляется вложение. http://temp.sh/SIDbq/AsyncDraw.rar
Вот смотри, там простейший пример - в одном потоке буфер заполняется (просто шумом), а в основном по таймеру выводится - без всякой синхронизации.
UA6527P

The trick
Постоялец
Постоялец
 
Сообщения: 808
Зарегистрирован: 26.06.2010 (Сб) 23:08

Re: SR2D и веб-камера (VB6). Удалось!

Сообщение The trick » 27.07.2025 (Вс) 14:40

С.Т. писал(а):Cam.SnapOne(1&)

Что такое 1? Где этот OCX? Уверен что формат можно задать при выводе без всякого сжатия и напрямую передавать его в SetDiBitsToDevice.
UA6527P

С.Т.
Обычный пользователь
Обычный пользователь
 
Сообщения: 50
Зарегистрирован: 10.03.2010 (Ср) 19:49

Re: SR2D и веб-камера (VB6). Удалось!

Сообщение С.Т. » 27.07.2025 (Вс) 14:48

The trick писал(а):
С.Т. писал(а):Cam.SnapOne(1&)

Что такое 1? Где этот OCX? Уверен что формат можно задать при выводе без всякого сжатия и напрямую передавать его в SetDiBitsToDevice.

1 - это просто обязательный параметр nResrv, который может быть любым и ни на что не влияет.
Влияет единица при ОТКРЫТИИ камеры: OpenCapDev(1) - открытие в другом потоке асинхронно и вывод кадров по событию (но в VB падает при закрытии камеры), а OpenCapDev(0) - синхронное открытие без создания потока, кадры снимаются только через SnapOne(любое_число).
Этот OCX во всех моих вложениях в этой теме (например, в первом посте).

Ваш проект скачал, огромное спасибо, сейчас изучу...

С.Т.
Обычный пользователь
Обычный пользователь
 
Сообщения: 50
Зарегистрирован: 10.03.2010 (Ср) 19:49

Re: SR2D и веб-камера (VB6). Удалось!

Сообщение С.Т. » 27.07.2025 (Вс) 14:58

Во-от! Правильно, напрямую в массив vbCreateThread шурует без ошибок, так что нужно мне выводить его из класса в буфер. Попробую! (А то вчера сделал пример с выводом кадров по AsynchDispMethodCall, и кадры выводятся долго, особенно при задержке формы. Напрямую по vbCreateThread гораздо шустрее!)

Единственное: SetDIBitsToDevice - не мой случай, мне обязательно нужно вывести картинку именно в класс (SR2D), т.к. она вкладывается сложным образом в суть программы, и без спрайтов не обойтись. Но из буфера в спрайт закинуть не проблема (только нужен формат ARGB). Завтра буду делать эти эксперименты! Спасибо от души!

Но снимок с камеры всё-таки удавалось получить только через стрим, напрямую он никуда не ложился...

След.

Вернуться в Мультимедиа

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 1

    TopList