• 【CV源码实现及调试】darknet中opencv的问题


    error

    ./src/image_opencv.cpp:5:10: fatal error: opencv2/opencv.hpp: No such file or directory
        5 | #include "opencv2/opencv.hpp"

    error

    ./src/image_opencv.cpp:12:1: error: ‘IplImage’ does not name a type
       12 | IplImage *image_to_ipl(image im)

    问题原因,说到底就是opencv include和lib的路径问题;

    安装opencv

    使用cmake安装,编译阶段会出现问题,或者编译安装成功,但是没有opencv_world库,最后直接使用cmake gui安装;

    解决方法:

    重新安装opencv,修改Makefile中opencv部分,然后更改src/image_opencv.cpp文件,使用Mat替换IplImage,且 remove all CV_ from opencv flags
     
    sudo apt install libopencv-dev  # opencv 4.2.0
    dpkg --list | grep opencv
    pkg-config --libs opencv4
    pkg-config --cflags opencv4

    Makefile

    LDFLAGS+= `pkg-config --libs opencv4` -lstdc++
    COMMON+= `pkg-config --cflags opencv4`

    src/image_opencv.cpp

    #ifdef OPENCV
    
    #include "stdio.h"
    #include "stdlib.h"
    #include "opencv2/opencv.hpp"
    #include "image.h"
    
    using namespace cv;
    
    extern "C" {
    // /*
    Mat image_to_mat(image im)
    {
        image copy = copy_image(im);
        constrain_image(copy);
        if(im.c == 3) rgbgr_image(copy);
        
        Mat m(cv::Size(im.w,im.h), CV_8UC(im.c));
        int x,y,c;
        
        int step = m.step;
        for(y = 0; y < im.h; ++y){
            for(x = 0; x < im.w; ++x){
                for(c= 0; c < im.c; ++c){
                    float val = im.data[c*im.h*im.w + y*im.w + x];
                    m.data[y*step + x*im.c + c] = (unsigned char)(val*255);
                }
            }
        }
        
        free_image(copy);
        return m;
    
    }
    
    image mat_to_image(Mat m)
    {
        int h = m.rows;
        int w = m.cols;
        int c = m.channels();
        image im = make_image(w, h, c);
        unsigned char *data = (unsigned char *)m.data;
        int step = m.step;
        int i, j, k;
        
        for(i = 0; i < h; ++i){
            for(k= 0; k < c; ++k){
                for(j = 0; j < w; ++j){
                    im.data[k*w*h + i*w + j] = data[i*step + j*c + k]/255.;
                }
            }
        }
        rgbgr_image(im);
        return im;
    }
    
    /*
    IplImage *image_to_ipl(image im)
    {
        int x,y,c;
        IplImage *disp = cvCreateImage(cvSize(im.w,im.h), IPL_DEPTH_8U, im.c);
        int step = disp->widthStep;
        for(y = 0; y < im.h; ++y){
            for(x = 0; x < im.w; ++x){
                for(c= 0; c < im.c; ++c){
                    float val = im.data[c*im.h*im.w + y*im.w + x];
                    disp->imageData[y*step + x*im.c + c] = (unsigned char)(val*255);
                }
            }
        }
        return disp;
    }
    
    image ipl_to_image(IplImage* src)
    {
        int h = src->height;
        int w = src->width;
        int c = src->nChannels;
        image im = make_image(w, h, c);
        unsigned char *data = (unsigned char *)src->imageData;
        int step = src->widthStep;
        int i, j, k;
    
        for(i = 0; i < h; ++i){
            for(k= 0; k < c; ++k){
                for(j = 0; j < w; ++j){
                    im.data[k*w*h + i*w + j] = data[i*step + j*c + k]/255.;
                }
            }
        }
        return im;
    }
    
    Mat image_to_mat(image im)
    {
        image copy = copy_image(im);
        constrain_image(copy);
        if(im.c == 3) rgbgr_image(copy);
    
        IplImage *ipl = image_to_ipl(copy);
        Mat m = cvarrToMat(ipl, true);
        cvReleaseImage(&ipl);
        free_image(copy);
        return m;
    }
    
    image mat_to_image(Mat m)
    {
        IplImage ipl = m;
        image im = ipl_to_image(&ipl);
        rgbgr_image(im);
        return im;
    }
    */
    // 
    void *open_video_stream(const char *f, int c, int w, int h, int fps)
    {
        VideoCapture *cap;
        if(f) cap = new VideoCapture(f);
        else cap = new VideoCapture(c);
        if(!cap->isOpened()) return 0;
        if(w) cap->set(CAP_PROP_FRAME_WIDTH, w);
        if(h) cap->set(CAP_PROP_FRAME_HEIGHT, w);
        if(fps) cap->set(CAP_PROP_FPS, w);
        return (void *) cap;
    }
    
    image get_image_from_stream(void *p)
    {
        VideoCapture *cap = (VideoCapture *)p;
        Mat m;
        *cap >> m;
        if(m.empty()) return make_empty_image(0,0,0);
        return mat_to_image(m);
    }
    
    image load_image_cv(char *filename, int channels)
    {
        int flag = -1;
        if (channels == 0) flag = -1;
        else if (channels == 1) flag = 0;
        else if (channels == 3) flag = 1;
        else {
            fprintf(stderr, "OpenCV can't force load with %d channels\n", channels);
        }
        Mat m;
        m = imread(filename, flag);
        if(!m.data){
            fprintf(stderr, "Cannot load image \"%s\"\n", filename);
            char buff[256];
            sprintf(buff, "echo %s >> bad.list", filename);
            system(buff);
            return make_image(10,10,3);
            //exit(0);
        }
        image im = mat_to_image(m);
        return im;
    }
    
    int show_image_cv(image im, const char* name, int ms)
    {
        Mat m = image_to_mat(im);
        imshow(name, m);
        int c = waitKey(ms);
        if (c != -1) c = c%256;
        return c;
    }
    
    void make_window(char *name, int w, int h, int fullscreen)
    {
        namedWindow(name, WINDOW_NORMAL); 
        if (fullscreen) {
            setWindowProperty(name, WND_PROP_FULLSCREEN, WINDOW_FULLSCREEN);
        } else {
            resizeWindow(name, w, h);
            if(strcmp(name, "Demo") == 0) moveWindow(name, 0, 0);
        }
    }
    
    }
    
    #endif
    View Code

    first isntall opencv,
    sudo apt install libopencv-dev
    then modify Makefile and src/image_opencv.cpp, including replace IplImage with Mat, and remove all CV_ from opencv flags.

    代码理解

    float val = im.data[c*im.h*im.w + y*im.w + x];   
    m.data[y*step + x*im.c + c] = (unsigned char)(val*255);
    or
    im.data[k*w*h + i*w + j] = data[i*step + j*c + k]/255.;

    主要是对 y*step + x*im.c + c的理解,没明白。。

    update 20220809

    之后发现这个和数据排列存放形式有关;

    opencv中cv::Mat的排列存放方式如下图所示,通常情况下Mat的每一行是连续存放的,也就是在内存上图像的所有数据存放成一行,在用指针访问时可以提供很大方便。

    感觉opencv和STBI图像库中的图像数据都是这样排列存储的,不过opencv是BGR而STBI是RGB;

    而darknet中image数据类型的存放方式是一个通道一个通道的存放的,详见src/image.c.

    image load_image_stb(char *filename, int channels)
    {
        int w, h, c;
        unsigned char *data = stbi_load(filename, &w, &h, &c, channels);
        if (!data) {
            fprintf(stderr, "Cannot load image \"%s\"\nSTB Reason: %s\n", filename, stbi_failure_reason());
            exit(0);
        }
        if(channels) c = channels;
        int i,j,k;
        image im = make_image(w, h, c);
        for(k = 0; k < c; ++k){
            for(j = 0; j < h; ++j){
                for(i = 0; i < w; ++i){
                    int dst_index = i + w*j + w*h*k;
                    int src_index = k + c*i + c*w*j;
                    im.data[dst_index] = (float)data[src_index]/255.;
                }
            }
        }
        free(data);
        return im;
    }

     这次分析是因为遇到问题,就是图像显示的颜色有点不对,比如黄色的显示的却是蓝色,感觉这个可能是和赋值的index有关,而且保存图像颜色正常,只是显示的时候不对。。。。之前测试没发现这个问题呀,不知道是一直就有还是现在才有这个问题。。

    之后发现是通道转换过程的细节问题,修改src/image_opencv.cpp中的一条语句即可;

    将 image_to_mat函数中的

    float val = im.data[c*im.h*im.w + y*im.w + x];

    替换为

    float val = copy.data[c*im.h*im.w + y*im.w + x];

    参考

    1. github_issue

    2. opencv-how-image-stored-memory

  • 相关阅读:
    true和false
    计算几何算法概览
    pixi.js 总结
    typescript 不用import?
    nodejs 新特性
    p2 碰撞
    Java学习笔记(十四)——Java静态工厂
    Java学习笔记(十三一)——Xml 常用知识总结
    读书笔记(二) ——《恶意》你善良吗?
    Spring学习(二)——Spring中的AOP的初步理解
  • 原文地址:https://www.cnblogs.com/happyamyhope/p/16480794.html
Copyright © 2020-2023  润新知