Ask Your Question
0

Laser pointer detect and track

asked 2015-01-11 11:29:04 -0600

McRex gravatar image

updated 2015-01-17 09:32:04 -0600

I try to create an interactive projector using the method of laser pointer detecting by color, form and saturation. The projection itself is not static, it is dynamic and has a lot of white elements. It is also very important to exclude the possibility of a wrong response to the metallic light glares. Here is the code i tried to use to detect the laser with Visual C++:

#include <opencv2\core\core.hpp>
#include <opencv2\highgui\highgui.hpp>
#include <opencv2\imgproc\imgproc.hpp>
#include <iostream>
#include <Windows.h>


int main() {
    cv::VideoCapture capWebcam(0);

// get screen resolution, which will be used in future
        int widthx = GetSystemMetrics(SM_CXSCREEN);
        int heighty = GetSystemMetrics(SM_CYSCREEN);
        std::cout << (widthx) << " X " << (heighty) << "\n\n";

//  webcam access
    if (capWebcam.isOpened() == false) {
        std::cout << "Error: Webcam don't work or can't be accessed\n\n";
        return(1);
    }

// creating various necessary staff
    cv::Mat matOriginal;
    cv::Mat matOriginalHSV;
    cv::Mat matProcessed;

    std::vector<cv::Vec3f> vecCircles;
    std::vector<cv::Vec3f>::iterator itrCircles;

    char charEscKey = 0;

    cv::namedWindow("Original", CV_WINDOW_AUTOSIZE);
    cv::namedWindow("Processed", CV_WINDOW_AUTOSIZE);

// creating trackbars
    cv::namedWindow("Trackbar", CV_WINDOW_AUTOSIZE);
    int hmin = 0, smin = 0, vmin = 0,
        hmax = 180, smax = 256, vmax = 256;
    cv::createTrackbar("H min:", "Trackbar", &hmin, hmax);
    cv::createTrackbar("H max:", "Trackbar", &hmax, hmax);
    cv::createTrackbar("S min:", "Trackbar", &smin, smax);
    cv::createTrackbar("S max:", "Trackbar", &smax, smax);
    cv::createTrackbar("V min:", "Trackbar", &vmin, vmax);
    cv::createTrackbar("V max:", "Trackbar", &vmax, vmax);


// main function
    while (charEscKey != 27) {
        if (capWebcam.read(matOriginal) == NULL) {
            std::cout << "Error: frame not readed from Cam\n\n";
            break;
        }

// converting to HSV
        cv::cvtColor(matOriginal, matOriginalHSV, CV_BGR2HSV);

// spliting channels, changing any channel from "matOriginalHSVchannels[0/1/2]" to "matZero" to remove it
        cv::Mat matZero;
        cv::Mat matOriginalHS;
        matZero = cv::Mat::zeros(cv::Size(matOriginalHSV.cols, matOriginalHSV.rows), CV_8UC1);
        cv::vector<cv::Mat> matOriginalHSVchannels(3);
        cv::split(matOriginalHSV, matOriginalHSVchannels);
        cv::vector<cv::Mat> channels;
        channels.push_back(matOriginalHSVchannels[0]);
        channels.push_back(matOriginalHSVchannels[1]);
        channels.push_back(matZero);
        cv::merge(channels, matOriginalHS);

// search of laser spot
        cv::inRange(matOriginalHS, cv::Scalar(hmin, smin, vmin), cv::Scalar(hmax, smax, vmax), matProcessed);

// blur
        cv::GaussianBlur(matProcessed,
            matProcessed,
            cv::Size(5, 5),
            2.2);

// circles search 
        cv::HoughCircles(matProcessed,
            vecCircles,
            CV_HOUGH_GRADIENT,
            1,
            matProcessed.rows / 8,
            100,
            50,
            7,
            20);

// draw circles
        for (itrCircles = vecCircles.begin(); itrCircles != vecCircles.end(); itrCircles++) {
            std::cout << "position x = " << (*itrCircles)[0]
                << ", y = " << (*itrCircles)[1]
                << ", z = " << (*itrCircles)[2] << "\n";

            cv::circle(matOriginalHS,
                cv::Point((int)(*itrCircles)[0], (int)(*itrCircles)[1]),
                1,
                cv::Scalar(255, 0, 0),
                CV_FILLED);

            cv::circle(matOriginalHS,
                cv::Point((int)(*itrCircles)[0], (int)(*itrCircles)[1]),
                (int)(*itrCircles)[2],
                cv::Scalar(255, 255, 0),
                2);

// set mouse cursor on laser coordinates
            int screenx = (int)((*itrCircles)[0] * 2.2);
            int screeny = (int)((*itrCircles)[1] * 1.2);
            SetCursorPos(screenx, screeny);

        }
// show windows
        cv::imshow("Original", matOriginalHS);
        cv::imshow("Processed", matProcessed);
        charEscKey = cv::waitKey(10);
    }
    return(0);
}

It is not possible to detect the laser pointer with this code even at the minimal brightness of the projector. All the more it will be necessary to use ... (more)

edit retag flag offensive close merge delete

Comments

"The screenshots are attached. "

No they aren't :)

FooBar gravatar imageFooBar ( 2015-01-11 11:31:39 -0600 )edit

now attached. just forgot to do it

McRex gravatar imageMcRex ( 2015-01-11 11:41:49 -0600 )edit

Have you tried to subtract and image without laser from an image with laser? A presentation is normally very static so you try to do some tracking.

FooBar gravatar imageFooBar ( 2015-01-11 11:52:07 -0600 )edit

The problem is that the content will be dynamic, not only slides but also video and other moving content.

McRex gravatar imageMcRex ( 2015-01-11 11:55:45 -0600 )edit
1

Does it have to be a red laserpointer? Or could you use a different wavelength than the projector, e.g. Infrared?

FooBar gravatar imageFooBar ( 2015-01-11 12:42:33 -0600 )edit

I need to use the projector with the presenter (laser pointer for presentations, in my case SpeedLink ACUTE Presenter).Doesn't the infrared pointer have a too high voltage to be used safely for presentations? The red pointers are easy to find and thus widespread. The green and blue lasers are not sold officially in my country. Are there any functions that allow to calibrate the webcam before detect the laser dot?

McRex gravatar imageMcRex ( 2015-01-11 13:02:23 -0600 )edit
1

if you got a cheap webcam to spare,

try an infrared-lowpass (i.e a piece of an old diskette) between cam-sensor and lense.

berak gravatar imageberak ( 2015-01-17 09:49:45 -0600 )edit

So the problem of detection can be solved only by use some material filter on cam lense, I was thinking about it, but not sure what material to use. I will try to do as you said.

McRex gravatar imageMcRex ( 2015-01-17 11:15:00 -0600 )edit

I think the same ... filter for ligh and some camera regulation (ex. light exposure etc etc).

gfx gravatar imagegfx ( 2015-01-17 11:22:48 -0600 )edit

Well.. most of red lasers pointers work in 650nm wavelength. I'm going to buy polarized filter, this one

Image

I will write the results here.

McRex gravatar imageMcRex ( 2015-01-22 13:23:59 -0600 )edit

1 answer

Sort by ยป oldest newest most voted
1

answered 2015-02-07 02:58:46 -0600

McRex gravatar image

Polarized filter for 650nm wavelength, works perfect. With it code works stable. But must add mat inversion in code

cv::Mat matProcessedInv;
cv::bitwise_not(matProcessed, matProcessedInv);

Thx FooBar and berak for tips

edit flag offensive delete link more

Comments

Could you post some new images? Which filter did you use?

FooBar gravatar imageFooBar ( 2015-02-07 11:35:46 -0600 )edit

Here is source image from cam with filter instaled, with windows and laser dot on the white window, Projector is set on max bright. Screenshot

And here is polarized lens for 650nm wavelength bought for 5$ filter

McRex gravatar imageMcRex ( 2015-02-09 14:06:27 -0600 )edit

Question Tools

1 follower

Stats

Asked: 2015-01-11 11:29:04 -0600

Seen: 11,610 times

Last updated: Feb 07 '15