OpenCV打开的图片在内存中如何与TBitmap相互转换,以便用TImage显示?

解决方案 »

  1.   

    不能转换,自己根据  cv::Mat 中的数据填充一张位图即可, 比如一个简单的方法,cv::Mat(C++) 或者IplImage(C语言)中,直接获取他的type,col,row,还有data属性,然后delphi通过这些参数直接创建一个位图填充像素即可。
      

  2.   


    是填充TBitmap的Pixels[x][y]吗?可以把data转成ScanLine吗?
      

  3.   

    data 是一个数据存储区指针而已,怎么转?你自己不填充没别的办法,而且C++还要注意  ,cv::Mat 如果定义成局部变量(不是new出来的),,data的内存是自动释放的。
      

  4.   


    我说的转的意思是包含数据复制,data的数据可以转换成ScanLine吗?
      

  5.   

    应该是都可以的,首先图像格式最好用32位或者24位图像格式,CV是可以转换的。其次ScanLine就是存储的图像中一行行的数据,所以只要将CV只的数据,按行的方式(如第一行是指针开始位置,第二行是开始位置加上图像宽度*4或者3,以此循环),复制到ScanLine就可以了。如果是FMX的话,可以用map、unmap的方式做,需要注意的一是图像是格式是否一致,否则要RB互换,二是坐标体系,bitmap好像是从左下开始的,VC好像是从左上吧,数据直接move就可以了。
      

  6.   


    CV的图像数据和ScanLine数据,R、G、B还是B、G、R顺序是一致的吗?每像素行图像数据末尾不知道有没有对齐填充?
    RB互换是什么意思?
      

  7.   

    windows的bitmap好像是按BGRA的顺序存放的,而有些技术规范是按RGBA方式存储的,如果转换的两边不同,就要把RB通道换一下,直白点就是把一个像素占用的四个字节中的第一个和第三个换一下就可以了(是不是一样的,,查下资料,或者运行看一下颜色对不对就知道了。)。关于对齐 ,,你使用32位模式,就没有对齐 问题的。速度也快,访问方式也简单,就只是一个点比24位多一个字节,
      

  8.   

    @lvjun 我浏览器出问题引用点不了了
    如何要RB互换,CV的图像数据就不能直接拷贝给ScanLine了?RB互换有函数吗?
    如果原来图像就是24位的,那要考虑对齐问题吗?
      

  9.   

    opencv里用imwrite写到一个bitmap文件再打开最简单了。
      

  10.   

    @DelphiGuy 我浏览器出问题引用点不了了写到文件再打开,不如在内存中操作速度快~
      

  11.   

    ......一行数据,无非是一个个点的数据的组合,而一个点是3个或者4个字节(24和32位RGB)的组合而已,所谓的互换,无非就是两个字节内容换一下就可以了。如果一定要到代码,就是用pbyte或者pansichar对应到图像数据或者scanline,例如第一个点就j m := p[0]; p[0] := p[2]; p[2] := m;就可以了,24位是有对齐的问题,scanline好像是按4字节对齐的吧。
      

  12.   

    @lvjun 我浏览器出问题引用点不了了比如24位图像,不知道有没有实际的代码?
      

  13.   

    如果opencv中Mat的内部存储结构可以和Tbitmap的内部存储结构对等的话(假设如此),可以:
    Mat src = imread("xxx");
    src.convertTo(src, 某种格式);
    TBitmap *bmp = new TBitmap;
    bmp->Width = src.cols;
    bmp->Height = src.rows;
    bmp->PixelFormat = 某种格式;
    memcpy(bmp->ScanLine[0], src.ptr, src.cols * src.elemSize);
    没有测试,可能需要cast某些类型,也可能需要循环每次复制一行,因为不清楚Mat的内部存储结构能否和BITMAP的每行像素字节数对齐到32位匹配。
      

  14.   

    原来你发在Delphi版,我还以为是CB版呢。
      

  15.   

    @DelphiGuy 我浏览器出问题引用点不了了Delphi版人气好一些~