【问题标题】:Opencv, drawing a box around an object from an imageOpencv,从图像中围绕对象绘制一个框
【发布时间】:2019-10-07 06:10:58
【问题描述】:

我正在做一个有趣的项目来了解有关 OpenCV 的更多信息。目前我想在给定图像的情况下绘制一个框。我有一个可以完成这项工作的工作函数,但是我在将 mouse_control 函数从 OpenCV 传递到 setMouseCallback 函数时遇到了一些问题。

我收到的错误是这样的:

 error C3867:  'Box::mouse_control': non-standard syntax; use '&' to create a pointer to member

当我尝试放置建议的参考时,我收到此错误:

error C2276:  '&': illegal operation on bound member function expression

我是 OpenCV 的新手,所以我不确定如何调试和修复我拥有的代码。

这是我正在处理的类的头文件:

#pragma once
#include "Image.h"

class Box : public Image
{
public:
    Box() = default;


    Mat draw_box(Mat& img, Rect box);
    void mouse_control(int event, int x, int y, int flag, void* param);

private:
    Rect g_rectangle;
    bool g_drawbox;


};

这是与头文件关联的 .cpp 文件:

#include "Box.h"
#define WINDOW_NAME "Drawing Rectangle"


void Box::mouse_control(int event, int x, int y, int flag, void* param)
{
    Mat& image = *(cv::Mat*) param;

    switch (event) 
    {
    case EVENT_MOUSEMOVE: 
    {    // When mouse moves, get the current rectangle's width and height
        if (g_drawbox) 
        {
            g_rectangle.width = x - g_rectangle.x;
            g_rectangle.height = y - g_rectangle.y;
        }
    }
    break;

    case EVENT_LBUTTONDOWN: 
    {  // when the left mouse button is pressed down,
       // get the starting corner's coordinates of the rectangle
        g_drawbox = true;
        g_rectangle = Rect(x, y, 0, 0);
    }
    break;

    case EVENT_LBUTTONUP: 
    {   // when the left mouse button is released,
        // draw the rectangle
        g_drawbox = false;
        if (g_rectangle.width < 0) 
        {
            g_rectangle.x += g_rectangle.width;
            g_rectangle.width *= -1;
        }

        if (g_rectangle.height < 0) 
        {
            g_rectangle.y += g_rectangle.height;
            g_rectangle.height *= -1;
        }
        draw_box(image, g_rectangle);
    }
    break;
    }
}

Mat Box::draw_box(Mat& img, Rect box)
{
    // Get input from user to draw box around object of interest
    rectangle(img, box.tl(), box.br(), Scalar(0, 255, 255), FILLED, LINE_8);
    Mat tempImage;
    //Mat srcImage(600, 800, CV_8UC3);
    //srcImage = Scalar::all(0);
    namedWindow(WINDOW_NAME);
    setMouseCallback(WINDOW_NAME, mouse_control, (void*)& img);
    while (1) {
        img.copyTo(tempImage);
        if (g_drawbox)
            draw_box(tempImage, g_rectangle);
        imshow(WINDOW_NAME, tempImage);
        if (waitKey(10) == 27)  // stop drawing rectanglge if the key is 'ESC'
            break;
    }
    return img;
}

错误发生在这里:

setMouseCallback(WINDOW_NAME, mouse_control, (void*)& img);

这是复制错误所需的主文件和其他头文件和cpp文件:

#include <iostream>
#include "Box.h"
#include "Image.h"


int main()
{

    // Declare image object and the name of the image (store image in project file)
    Image img_obj;
    std::string image_name = "hawaii.png";

    // Read and display image
    auto img1 = img_obj.get_image(image_name);
    img_obj.display(img1);

    Rect g_rectangle;
    Box b;
    auto new_img = b.draw_box(img1, g_rectangle);
    b.display(new_img);


    std::cin.get();
}

#pragma once
#include <opencv2/opencv.hpp>

using namespace cv;


class Image
{
public:
    Image() = default;


    // Member functions
    const Mat get_image(std::string& image_name);
    void display(Mat& img);
};

#include "Image.h"


const Mat Image::get_image(std::string& image_name)
{
    Mat img = imread(image_name);
    return img;
}

void Image::display(Mat& img)
{
    namedWindow("image", WINDOW_NORMAL);
    imshow("image", img);
    waitKey(0);
}

【问题讨论】:

    标签: c++ opencv


    【解决方案1】:

    会员功能和普通功能是两个不同的东西。

    setMouseCallback 函数作为回调普通函数,其签名为:

    handleMouse(int event, int x, int y, int flag, void* param)
    

    你尝试调用setMouseCallback 传递mouse_control 作为回调,它不能工作,因为mouse_controlBox 类的成员函数。您为特定对象调用成员函数,您不能将其称为“独立” - 没有对象。这就是您的代码无法编译的原因。

    解决方案?

    回调的最后一个参数是void*。现在,您将指针传递给Image,但您可以将指针传递给Box,不是吗?因此,您可以将mouse_control 设为Box 类的静态函数:

    class Box : public Image {
    public:
        Box() = default;
        Mat draw_box(Mat& img, Rect box);
        static void mouse_control(int event, int x, int y, int flag, void* param); // static added
    

    (静态函数不需要调用对象)。 你通过调用传递的指针:

    setMouseCallback(WINDOW_NAME, mouse_control, this);
    

    里面:

    void Box::mouse_control(int event, int x, int y, int flag, void* param) {
        Box* box = (Box*)param;
    
        // you can access member variable of Box by 
        box->g_rectangle
        box->draw_box
    

    您还需要了解如何存储img,可能作为Box 的数据成员?或者您可以制作一些包装器,例如

    struct Foo {
        Box* box;
        Image img;
    };
    

    并将指向此结构的指针作为回调的最后一个参数传递。

    【讨论】:

    • 谢谢,它现在可以工作了,但我需要让我的程序在输入图像上绘制一个框并存储我绘制的框。这就是你在上一条评论中提到的吗?
    • Uu,我错过了 BoxImage 的基类,这个额外的结构包装器 Foo 不是必需的:) 你的意思是什么 并存储我画的框,你的Box 类有g_rectangle 成员变量,它已经存储了你的画框?
    【解决方案2】:

    C++ 成员函数具有与常规函数不同的内部签名。它将隐式包含指向函数签名的指针。否则,如果函数必须修改其中的一些,函数怎么知道要修改哪些对象内部数据?

    因此,您的成员函数MouseControl() 的签名将如下所示:

    void mouse_control(Box *object, int event, int x, int y, int flag, void* param);
    

    显然这不被 OpenCV 库接受(函数指针类型不匹配,即额外的 Box * object 使其失败。)。

    要修复它,请尝试以下两种方法之一:

    1. 使用常规函数而不是类成员函数。

    2. 使用static class function(类静态函数未绑定到对象,因此没有“签名中的额外参数”,即Box *object)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-03-19
      • 2021-01-03
      • 2017-03-05
      • 2018-03-26
      • 1970-01-01
      • 2021-12-19
      • 2012-06-15
      • 2015-07-21
      相关资源
      最近更新 更多