o派大猩o 2021-10-15 17:46 采纳率: 0%
浏览 105
已结题

求,opencv写BMP格式,出现图像倾斜错位问题

上代码,

int Mat2Bmp(cv::Mat * pMat, uchar * & pBmp, DWORD & size)
{
    if (!pMat)
    {
        return -1;
    }
    
    IplImage img(*pMat);
    /////////////////////////////////创建bmp空白图片///////////////////////////
    int depth = pMat->depth();
    int channels = pMat->channels();
    int width = pMat->cols;
    int height = pMat->rows;

    // 获取图像每个像素的位数
    // depth 代表每个通道元素的宽度,0:CV_8U
    UINT pixelSize = (8 << (depth / 2)) * channels;

    // bmp规定每一行的长度必须是4的整数倍, pMat->cols * pixelSize / 8 为每一行有效数据长度 
    //UINT lineSize = ((width * pixelSize / 8) + 3) / 4 * 4;
    UINT lineSize = width * pixelSize / 8;

    // 计算需要的调色板的大小,以便为bmp图像申请内存空间
    // 只有148位图才需要调色板(1->2, 4->16, 8->256),因为162432位有足够的空间以便自由组合

    UINT colorTableSize = 2 * sizeof(RGBQUAD);

    // bmp图片的大小, sizeof(BITMAPFILEHEADER) = 14, sizeof(BITMAPINFOHEADER) = 40
    size = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+colorTableSize + height * lineSize;
    pBmp = (uchar*)malloc(size);
    if (!pBmp)
    {
        return -2;
    }
    memset(pBmp, 0, size);

    ///////////////////////////////////为bmp图片的调色板赋值/////////////////////////////////
    // 8位图
    if (8 == pixelSize)
    {
      // 只有148位图才需要调色板(1->2, 4->16, 8->256),因为162432位有足够的空间以便自由组合
      RGBQUAD* pColorTable = (RGBQUAD*)(&pBmp[sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)]);
      pColorTable[1].rgbBlue = pColorTable[1].rgbGreen = pColorTable[1].rgbRed = pColorTable[1].rgbReserved = 0;//调色板颜色为黑色对应的索引为0
      pColorTable[0].rgbBlue = pColorTable[0].rgbGreen = pColorTable[0].rgbRed = 190;//白色对应的索引为150-255
      //for (int i = 0; i < 256; ++i)
      //{
      //    // 灰阶调色板
      //    pColorTable[i].rgbRed = i;
      //    pColorTable[i].rgbGreen = i;
      //    pColorTable[i].rgbBlue = i;

      //    // 也可以创建彩色调色版
      //}
    }

    /////////////////////////////////为bmp图片的文件头赋值/////////////////////////////////
    BITMAPFILEHEADER * pFileHead = (BITMAPFILEHEADER *)pBmp;
    pFileHead->bfType = 0x4D42; // 0x4D42 代表 “BM”,位图标志
    pFileHead->bfSize = size;
    pFileHead->bfOffBits = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+colorTableSize; // 图像数据偏移量

    /////////////////////////////////为bmp图片的信息头赋值/////////////////////////////////
    BITMAPINFOHEADER * pInfoHead = (BITMAPINFOHEADER *)(&pBmp[sizeof(BITMAPFILEHEADER)]);
    pInfoHead->biSize = 40;             // 信息头的大小
    pInfoHead->biWidth = width;
    pInfoHead->biHeight = height;
    pInfoHead->biPlanes = 1;            // 图像平面数,rgb为1?什么时候大于1?
    pInfoHead->biBitCount = pixelSize;  // 图像每个像素所占的位数
    pInfoHead->biCompression = 0;       // 0:不压缩,1:REL8, 2:REL4
    pInfoHead->biSizeImage = height * lineSize;     // 图像数据大小
    pInfoHead->biXPelsPerMeter = 0;     // 水平方向像素/米,分辨率
    pInfoHead->biYPelsPerMeter = 0;     // 垂直方向像素/米,分辨率
    pInfoHead->biClrUsed = 2;           // BMP图像使用的颜色,0:表示使用全部颜色
    pInfoHead->biClrImportant = 0;      // 重要的颜色数,0:所有的颜色都重要,当显卡不能够显示所有颜色时,辅助驱动程序显示颜色


    /////////////////////////////////为bmp图片的图像数据赋值/////////////////////////////////
    // BMP 和 Mat 数据都是自左向右,但是BMP是自下而上,Mat是自上而下,故而在数据转换时需要颠倒数据上下位置

    //uchar * pBmpData = pBmp + pFileHead->bfOffBits;
    uchar * pBmpData = pBmp + pFileHead->bfOffBits +height * lineSize; // 最后一行尾地址
    uchar * pMatData = pMat->data;  // 第一行首地址
    // 将Mat从上往下一行一行拷给BMP

    for (int i = 0; i < height; ++i)
    {
        // 这里的 width 代表水平方向的像素个数,但是每个像素占1个字节,通过查表索引(RGB
        // 每次拷贝一行
        
        pBmpData -= lineSize;
        memcpy(pBmpData, pMatData, lineSize);
        pMatData += lineSize;
    }
    return 0;
}

        cv::Mat bin;
    threshold(gray, bin, 0, 255, CV_THRESH_OTSU);
    cv::bitwise_not(bin, bin);

    uchar* pBmp = NULL;
    DWORD size = 0;
    Mat2Bmp(&bin, pBmp, size);
    CxImage srcimage(pBmp, size,CXIMAGE_FORMAT_BMP);
        if (srcimage.IsValid())
    {
        srcimage.SetXDPI(XDPI);
        srcimage.SetYDPI(YDPI);
        srcimage.Save(filename, dstImagetype);
    }

img

二值化后想将MAT写BMP格式的内存,但是发现图片出现倾斜的现象,网上说可能是行字节对齐问题,实在不知道怎么修改。还有个问题,就是我已经使用bitwise_not将颜色取反,介个输出的BMP文件颜色也对不上,可能是调色板的问题,有知道的麻烦也解答一下,感激不尽。

  • 写回答

0条回答 默认 最新

    报告相同问题?

    问题事件

    • 系统已结题 10月23日
    • 创建了问题 10月15日

    悬赏问题

    • ¥100 求Web版SPC控制图程序包调式
    • ¥20 指导如何跑通以下两个Github代码
    • ¥15 大家知道这个后备文件怎么删吗,为啥这些文件我只看到一份,没有后备呀
    • ¥15 C++为什么这个代码没报错运行不出来啊
    • ¥15 一道ban了很多东西的pyjail题
    • ¥15 关于#r语言#的问题:如何将生成的四幅图排在一起,且对变量的赋值进行更改,让组合的图漂亮、美观@(相关搜索:森林图)
    • ¥15 C++识别堆叠物体异常
    • ¥15 微软硬件驱动认证账号申请
    • ¥15 GPT写作提示指令词
    • ¥20 根据动态演化博弈支付矩阵完成复制动态方程求解和演化相图分析等