HiAsm - Конструктор программ

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » HiAsm - Конструктор программ » Между делом » Веб-камера отражает картинку по вертикали


Веб-камера отражает картинку по вертикали

Сообщений 1 страница 2 из 2

1

В качестве веб-камеры используется камера заднего вида автомобиля, а она внутри себя переворачивает картинку справа налево. Естественно, неплохо было бы её перевернуть обратно, но стандартный компонент WebCam такой функцией не обладает. Вроде бы решение очевидно: получить картинку с камеры и уже графическими компонентами перевернуть её обратно, но вот тут возникла проблема: WebCam не выдаёт картинку в поток, он только отрисовывает её на указанном элементе.
https://forumupload.ru/uploads/001b/10/a7/10/t302155.jpg

Что же я перепробовал:
1. Метод компонента doSaveDIB (сохраняет кадр в файл) для последующей загрузки картинки из файла и переворота. Однако это придётся делать несколько раз в секунду, что сильно замедлит программу.
2. Метод doEditCopy - помещает кадр в буфер обмена. Однако не очень хорошо, если программа без ведома пользователя будет что-то помещать в буфер - тогда пользователь не сможет с ним работать.
3. Может быть, есть какие-то другие методы, не реализованные в WebCam? Порывшись на сайте https://learn.microsoft.com/en-us/windo … edit-copy, я ничего подходящего не нашёл. Да, есть какая-то колбэк-функция при получении очередного кадры с камеры, но ничего не описано, где именно там хранится картинка. Соответственно, в интернетах я по этому поводу тоже толком ничего не нашёл. Не выдаёт этот функционал картинку в поток/переменную, а только её отрисовывает!
4. Дальше уже пошли опыты в IC. Опробована фукнция

Код:
BitBlt(bmp.Canvas.Handle, 0, 0, 320, 240, GetDC(h), 0, 0, SRCCOPY);

, где h - это указатель на окно видеозахвата, получаемый с нижней точки компонента WebCam, а bmp - созданная временная картинка. Способ рабочий, да вот только исходный (т.е. отражённый справа налево) кадр при этом должен оставаться видимым на форме, иначе ничего не работает. А зачем отображать исходное, неправильное изображение?
5. Были мысли, может, методу doSaveDIB подсунуть имя какого-нибудь виртуального файла, на самом деле указывающего на участок памяти, но в сети я так и не нашёл толкового способа это сделать.
6. Спросил ИИ: ГПТ, copilot, replit... Видели бы вы, ЧТО они мне навыдавали! Какие-то несуществующие функции типа capGetFrame (существует только capGrabFrame, она позволяет получать один кадр с камеры в окно просмотра),

Код:
SendMessage(h, WM_CAP_COPY, 0, LPARAM(Bmp.Handle))

(это сообщение копирует кадр в буфер обмена, оно и используется в doEditCopy, но LParam там совсем не используется!). В общем, почти всё нерабочее, для моей цели не подошло ничего.
7. Сунулся было в DirectX - читал, что там расширенные возможности видеозахвата, но кода там на неделю разбираться для такой мелочи, как разворот картинки.
...

Решение нашлось, отуда не ждали. Есть такой стиль окон - WS_EX_LAYOUTRTL, он отражает справа налево само окно. Отражение выполняется самой виндой, достаточно установить этот стиль - и она сама будет разворачивать окно вместе с картинкой!

код
Код:
Add(WebCam,1803333,609,322)
{
 RefreshRate=200
 FileDIB="a.bmp"
 FileVideo="cam.avi"
 Point(doVideoSource)
 Point(doVideoFormat)
 Point(doVideoCompression)
 Point(doSaveDIB)
 link(WinHandle,14074503:Handle,[])
}
Add(Button,7768292,490,266)
{
 Left=5
 Top=35
 Caption="Source"
 link(onClick,1803333:doVideoSource,[(566,272)(566,342)])
}
Add(Button,14395040,483,308)
{
 Left=5
 Top=55
 Caption="Format"
 link(onClick,1803333:doVideoFormat,[(562,314)(562,349)])
}
Add(Button,7859332,483,350)
{
 Left=5
 Top=75
 Caption="Compress"
 link(onClick,1803333:doVideoCompression,[])
}
Add(Image,14074503,616,266)
{
 Left=65
 Top=5
 Width=320
 Height=263
 Point(Handle)
 Point(doRefresh)
}
Add(Hub,5680976,532,203)
{
 link(onEvent1,1803333:doDisConnect,[(583,209)(583,335)])
 link(onEvent2,1803333:doConnect,[(578,216)(578,328)])
}
Add(Button,11636729,490,203)
{
 Left=5
 Top=10
 Caption="On"
 link(onClick,5680976:doEvent1,[])
}
Add(InlineCode,14009132,609,399)
{
 WorkPoints=#1:a|
 EventPoints=#5:onBmp|
 DataPoints=#8:dtHandle|
 Code=#42://Отражение картинки с камеры по вертикали|15:unit HiAsmUnit;|0:|9:interface|0:|38:uses windows,kol,Share,Debug,hiWebCam;|0:|24:var rtl:boolean = false;|0:|4:type|28: THiAsmClass = class(TDebug)|10:   private|9:   public|23:    dtHandle:THI_Event;|20:    onBmp:THI_Event;|42:    procedure a(var dt:TData; index:word);|0:|5: end;|0:|14:implementation|0:|24:procedure THiAsmClass.a;|30:var h:longword; //bmp:PBitmap;|34:const WS_EX_LAYOUTRTL = $00400000;|5:begin|31: h := ToIntegerEvent(dtHandle);|29: //Bmp := NewBitmap(640,480);|14: {xy.x := 100;|13: xy.y := 100;|55: SendMessage(h, WM_CAP_SET_SCROLL, 0, longint(@(xy)));}|81: //SendMessage(h, WM_CAP_SET_CALLBACK_FRAME, 0, longint(@FrameCallbackFunction));|43: //SendMessage(h, WM_CAP_GRAB_FRAME, 0, 0);|70: //BitBlt(bmp.Canvas.Handle, 0, 0, 320, 240, GetDC(h), 0, 0, SRCCOPY);|33: //Bmp.Canvas.Handle := GetDC(h);|0:|97: if rtl then SetWindowLong(h, GWL_EXSTYLE, GetWindowLong(h, GWL_EXSTYLE) and not WS_EX_LAYOUTRTL)|87:  else SetWindowLong(h, GWL_EXSTYLE, GetWindowLong(h, GWL_EXSTYLE) or WS_EX_LAYOUTRTL);|16: rtl := not rtl;|26: //_hi_OnEvent(onBmp,Bmp);|4:end;|0:|4:end.|
 link(dtHandle,1803333:Handle,[])
}
Add(Button,12790683,490,399)
{
 Left=5
 Top=100
 Caption="RTL"
 link(onClick,14009132:a,[])
}

0

2

3042
Делал для вэбки когда-то через DirectShow. Там можно грабить в битмаp, потом флипнуть. Но твой способ вероятно лучше.
Хотя функционала у штатного явно не достаточно.
Вот моя поделка если что Ссылка

0


Вы здесь » HiAsm - Конструктор программ » Между делом » Веб-камера отражает картинку по вертикали


Рейтинг форумов | Создать форум бесплатно