Программка для интерактивной доски irMouse

Че-то проекты на форуме не двигаются :thinking:
Наконец-то руки дошли выложить: irMouse на SourceForge
Позволяет объединить проектор, доработанную напильником вебкамеру и простую инфракрасную указку в интерактивную доску.
Написана в Lazarus с применением OpenCV.
На страничке есть видео что к чему + несколько видео just for fun + мануал в архиве для тех, кто решится.
Сам использую и тащусь.
Может, кому-то пригодится тоже.

2 лайка

В Wine (на Ubuntu/PopOS 20.04) запустилось, но камеру не нашло )

Ну, есть у меня мечта кое-чего переписать и скомпилить под Linux.
Lazarus должен затащить

Да у меня указки и проектора всё равно нет :smiley:

В VirtualBox нашлась камера )

Идея насчет переписать малёхо под Линукс у меня была и до этого момента)

Проблему с отсутствием проектора можно решить)

1 лайк

Эх, спустя длительное время засел за переписывание софтового ввода мыши с помощью mouseandkeyinput для кроссплатформенности (до этого эмуляция мыши была через WinAPI). Сегодня оно заработало, но тут я наткнулся на платформо-зависимую процедуру перевода изображение из формата openCV в bitmap… :sleepy:

To be continued…

Так а в чем трабл?
Конвертация посредством промежуточной переменной…
convert Mat to Bitmap Opencv for Android

Трабл в том, что я возомнил себя программистом.
Кадры с вебкамеры хранятся в формате IplImage, вот его надо в bitmap.

Кадры удобней выхвативать из потока и сохранять снетшопы в удобном формате.

Есть код по захвату потоков с бинокуляра для последующего сохранения в файлы. Цель такого вояния, калибровка стереопары. Если интересно могу выложить…

P. S.
Да вот в принципе и код:

Код. Коменты на Украинском языке
/*StSnap.cpp
Захоплення та декодування відео потоків
використовуйте дві USB відеокамери сумісні з ПК
які підтримують розподільчу здатність(640х480)
Підключення камер в різні USB чіпи, наприклад першу камеру в USB-3.0 другу в USB-2.0
Або одну камеру до фронтального роз'єму іншу подлючайте до тиловіх роз'ємів
*/
#include <windows.h>
#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/core.hpp>
#include <opencv2/calib3d.hpp>
#include <opencv2/highgui.hpp>
#include "Config.h"

using namespace cv;
using namespace std;

int main(int argc, char* argv[]) {
	
	VideoCapture capr(0);      //визначаємо камери
	if (capr.isOpened() == false) { cout << "error: Webcam No.1 connect unsuccessful\n";  system("pause");  return(0); }
	VideoCapture capl(1);
	if (capl.isOpened() == false) { cout << "error: Webcam No.2 connect unsuccessful\n";  system("pause"); return(0); }
	// Camera "NoName"
	capl.set(CV_CAP_PROP_FRAME_HEIGHT, 480);
	capl.set(CV_CAP_PROP_FRAME_WIDTH, 640);
	// Camera " HQ-TECH, model: WU-66512.0M"
	capr.set(CV_CAP_PROP_FRAME_HEIGHT, 480);
	capr.set(CV_CAP_PROP_FRAME_WIDTH, 640);
	
	namedWindow("Left");
	namedWindow("Right");

	cout << "Press 's' to save capture ..." << endl;
	char choice = 0;
	int count = 0;
	while (choice != 'q') {
		//захоплення потоків
		capl.grab();
		capr.grab();
		//операії декодування
		Mat framel, framer;
	
		capl.retrieve(framel);
		capr.retrieve(framer);

		if (framer.empty() || framel.empty()) break;

		imshow("Left", framel);
		imshow("Right", framer);
		if (choice == 's')
		{
			//збереження *.jpg та очікування «Key» 's' або 'q'
			stringstream r_name, l_name;
			l_name << "left" << setw(4) << setfill('0') << count << ".jpg";
			r_name << "right" << setw(4) << setfill('0') << count << ".jpg";
			imwrite(string (LEFT_FOLDER) + l_name.str(), framel);
			imwrite(string(LEFT_FOLDER) + l_name.str(), framel);
			cout << "Saved set left "<< count<< endl;
			imwrite(string (RIGHT_FOLDER) + r_name.str(), framer);
			imwrite(string(RIGHT_FOLDER) + r_name.str(), framer);
			cout << "Saved set right" << count << endl;
			count++;
		}
		choice = char(waitKey(1));
	}
	destroyAllWindows();
	capl.release();
	capr.release();
	return 0;
}

Фича в том что по нажатию клавиши “s” хватаем текущие кадры обоих камер из потока и сохраняем в файлы.

Для функций поиска объектов на кадре нужен формат IplImage

Не то имел ввиду. Если нужно сохранять кадры в файл то делать это через промежуточную переменную. И далее ту же переменную можно обрабатывать хоть с ImplImage, хоть напрямую с Mat

Изучив опыт других граждан, у меня получилось адаптировать их наработки для Lazarus.
Вышел такой кусочек:

uses
  SysUtils, Graphics, IntfGraphics;

{...}

//Преобразует изображение IplImage в Bitmap
function cvCreateBitmap(AIplImage: PIplImage): TBitmap;
var
  bmp: TBitmap;
  img: TLazIntfImage;

  deep: Integer;
  i, j, K, wStep, Channels: Integer;
  data: PByteArray;
  pb: PByteArray;
begin
  Result:=nil;

  if Assigned(AIplImage) then
  begin
    bmp:=TBitmap.Create;

    bmp.Width:=AIplImage^.Width;
    bmp.Height:=AIplImage^.Height;
    deep:=AIplImage^.nChannels*AIplImage^.depth;

    case deep of
      8:  bmp.PixelFormat:=pf8bit;
      16: bmp.PixelFormat:=pf16bit;
      24: bmp.PixelFormat:=pf24bit;
      32: bmp.PixelFormat:=pf32bit;
    end;

    wStep:=AIplImage^.WidthStep;
    Channels:=AIplImage^.nChannels;
    data:=PByteArray(AIplImage^.ImageData);

    img:=bmp.CreateIntfImage;

    for i:=0 to img.Height-1 do
    begin
      pb:=img.GetDataLineStart(i);

      for j:=0 to img.Width-1 do
      begin
        for K:=0 to Channels-1 do
          pb^[3*j+K]:=data^[i*wStep+j*Channels+K];
      end;
    end;

    bmp.LoadFromIntfImage(img);
    img.Free;

    Result:=bmp;
  end;
end;

Применение:

var
  bmp: TBitmap;

{...}

bmp:=cvCreateBitmap(some_IplImage);
try
  if Assigned(bmp) then
    PaintBox1.Canvas.Draw(0, 0, bmp);
finally
  FreeAndNil(bmp);
end;

Пытаюсь перенести на Ubuntu…

В паскале-подобных языках не очень силен, какой общий алгоритм задачи?

Задача выводить кадры на визуальный компонент, чтобы пользователь мог настроить камеру, выполнить калибровку.

Так брать кадры из потока не обязательно с IplImage.
Что подразумевается под

?
Выполнить калибровку относительно разрешения и фокусного расстояния?

При калибровке пользователь указывает на поверхности (на стене, например) четыре точки, соответствующие углам рабочего стола.
В первом посте есть ссылка, по ней еще ссылка на видео, для чего это огород вобще.

Сглупил, не посмотрел ссылку.
Понял что этот продукт аналог Kinect
Как боритесь с распознаванием ИК луча при помощи одной камеры? Камера видит всю траекторию луча и могут быть ошибки при детектировании.
Для точного детектирования точки ИК луча необходимо строить карту глубины (depth), что возможно с минимальным числом ошибок при стерео паре. А стереопару находим при помощи двух камер.
Иначе луч будет засвечивать прямую на изображении, и распознать куда он уперся будет сложно.

P. S.
Посмотрел видео по ссылке возник вопрос по косынке.
На видео человек тыцкает указкой в карту и передвигает, это так же ИК луч?

Камера видит пятно на поверхности, сам луч не видно.
Ошибки могут быть, если в кадре что то блестящее, при мощном естественном освещении, тогда возникают множественные пятна.

Везде ИК

После трех дней настройки Linux Mint на virtualBox, установки openCV библиотек нужной версии, установки Lazarus, имею некоторый результат:

Из плюсов:

  • Получилось уйти от виндозависимых функций
  • Камеру видит, изображение идет

Из минусов:

  • Сложно с настройками камеры
  • Эмуляция мыши пока не очень

Продолжаю раскопки.

Прошло несколько часов…

Удалось поправить эмуляцию (до этого нажатая кнопка мыши не отпускалась).
Кино с примером, как теперь всё хорошо

Для настройки камеры в Linux Mint установил Video 4 Linux Control Panel, однако настроек там нет, разве что яркость, которая по факту ни на что не влияет.
Снимок экрана_2020-10-29_16-00-15

Погуглив инфу, надеюсь, что это особенность virtualBox, которая просто не передает управление настройками камеры в виртуальную ОС.