c++ - FreeImage+OpenCV - 16 位图像失真

标签 c++ opencv depth freeimage

我正在尝试加载图像,因为我必须对其应用算法。 如果我加载一个每 channel 8 位的图像,则没有问题,但如果我加载一个 16bpc 的图像,它就会“毁掉”。不幸的是,由于我没有足够的声誉,我无法上传图片。

这些是它们的链接:

要么是源码,要么是8bpc的处理结果

http://postimg.org/image/gc0zf2lp5/

..如果我处理保存为 16bpc 的相同图像的结果

http://postimg.org/image/5nnwee7df/

这是代码:

FreeImage_Initialise();
FREE_IMAGE_FORMAT formato = FreeImage_GetFileType(argv[1], 0);
FIBITMAP* imagetmp = FreeImage_Load(format, argv[1]);
FIBITMAP* image = FreeImage_Rotate(imagetmp, 180);
FreeImage_FlipHorizontal(image);
int depth = FreeImage_GetBPP(image);
printf("depth = %d\n", FreeImage_GetPitch(image));
cv::Mat img(FreeImage_GetHeight(image), FreeImage_GetWidth(image), CV_MAKETYPE(depth/3, 3), FreeImage_GetBits(image), FreeImage_GetPitch(image));
FreeImage_DeInitialise();

它会是什么?

最佳答案

depth 的值不是您所期望的。它指的是 OpenCV 深度定义为:

#define CV_8U   0
#define CV_8S   1
#define CV_16U  2
#define CV_16S  3
#define CV_32S  4
#define CV_32F  5
#define CV_64F  6

因此,如果您知道您的 FreeImage 是 FIT_RGB16 类型,您应该使用值 CV_16U 作为深度。您还应该从 RGB 转换为 BGR,因为 OpenCV Mat 是 BGR 格式。

这里的例子:

#include <FreeImage.h>
#include <opencv2\opencv.hpp>
using namespace cv;

int main()
{
    FreeImage_Initialise();
    FREE_IMAGE_FORMAT format = FreeImage_GetFileType("path_to_image", 0);
    FIBITMAP* imagetmp = FreeImage_Load(format, "path_to_image");
    FIBITMAP* image = FreeImage_Rotate(imagetmp, 180);
    FreeImage_FlipHorizontal(image);
    int depth = FreeImage_GetBPP(image);
    printf("depth = %d\n", FreeImage_GetPitch(image));

    // FreeImage to Mat conversion
    cv::Mat img(FreeImage_GetHeight(image), FreeImage_GetWidth(image), CV_MAKETYPE(CV_16U, 3), FreeImage_GetBits(image), FreeImage_GetPitch(image));
    cvtColor(img, img, CV_BGR2RGB);

    FreeImage_DeInitialise();

    return 0;
}

请注意,您也可以避免创建额外的 FreeImage 图像只是为了翻转它,并让 OpenCV Mat 来执行此操作:

#include <FreeImage.h>
#include <opencv2\opencv.hpp>
using namespace cv;

int main()
{       
    FreeImage_Initialise();
    FREE_IMAGE_FORMAT format = FreeImage_GetFileType("path_to_image", 0);
    FIBITMAP* image = FreeImage_Load(format, "path_to_image");

    // FreeImage to Mat conversion
    cv::Mat img(FreeImage_GetHeight(image), FreeImage_GetWidth(image), CV_MAKETYPE(CV_16U, 3), FreeImage_GetBits(image), FreeImage_GetPitch(image));
    cvtColor(img, img, CV_BGR2RGB);
    flip(img,img,0);

    FreeImage_DeInitialise();

    return 0;
}

你不能用cv::imshow 直接显示这个图像。您需要将其转换为 CV_8UC3 类型才能看到。例如,您可以在 imshow 之前调用 convertScaleAbs(img, img);

或者可以引用this回答将所有类型的 FreeImage 转换为 OpenCV Mats 的函数。

关于c++ - FreeImage+OpenCV - 16 位图像失真,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31866822/

相关文章:

c++ - Gsoap Http 事件回调

c++ - 在基类中引用不同大小的 std::array 而不是 std::array

c++ - 类 Vector2 最终 : shared_ptr<Vector2> correct or not (Updated! )

opencv - 用彩色图像进行人脸识别?

python - Ros 订阅者不是最新的

c++ - 计算树的深度和后代

c++ - 有不合逻辑错误的数字猜谜游戏

c++ - 仅 block 的 HoG 特征

c++ - OpenCV imwrite保存完整的黑色jpeg

python - 从原始 RGB 深度图像到灰色的错误转换