【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安装;
解决方法:
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
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#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
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;
完
心正意诚,做自己该做的事情,做自己喜欢做的事情,安静做一枚有思想的技术媛。
版权声明,转载请注明出处:https://www.cnblogs.com/happyamyhope/