简体   繁体   English

为什么我的简单对比算法不适用于 Cimg

[英]Why is my simple contrast algorithm not working with Cimg

I've been going over my code for a few hours now and I'm not sure why this contrast algo isn't working.我已经检查我的代码几个小时了,我不确定为什么这种对比算法不起作用。

Following this guide I've used the small algorithm given on the post.按照本指南,我使用了帖子中给出的小算法。 However I did mine using HSI color scheme because my pictures need to be in color.但是我使用 HSI 配色方案,因为我的图片需要是彩色的。 I have noted the changes for HSI in the post however they didn't give me a step by step on exactly how to do it.我已经在帖子中注意到 HSI 的变化,但他们并没有一步一步地告诉我如何做到这一点。 Also they're using pillow, whereas I'm using Cimg.他们也在用枕头,而我用的是 Cimg。

My code compiles and runs with no errors.我的代码编译并运行没有错误。 But the result is a very dark image.但结果是一个非常暗的图像。 在此处输入图像描述

I was hoping for an output similar to what I get if increasing contrast using camera raw filter in photoshop.我希望 output 类似于我在 Photoshop 中使用相机原始滤镜增加对比度时得到的结果。 This is the a result of maxing the photoshop contrast slider:这是最大化 Photoshop 对比度 slider 的结果: 在此处输入图像描述

This is the tail of the modified intensity values and the min max values:这是修改后的强度值和最小最大值的尾部:

old Intensity 0.422222
new Intensity 0.313531
old Intensity 0.437909
new Intensity 0.353135
old Intensity 0.437909
new Intensity 0.353135
old Intensity 0.436601
new Intensity 0.349835
old Intensity 0.439216
new Intensity 0.356436
old Intensity 0.443137
new Intensity 0.366337
old Intensity 0.45098
new Intensity 0.386139
old Intensity 0.458824
new Intensity 0.405941
old Intensity 0.461438
new Intensity 0.412541
min 0.298039
max 0.694118

Hope someone can help, thanks.希望有人能帮忙,谢谢。

#include <iostream>
#include "CImg.h"

int main() {
  cimg_library::CImg<float> lenaCondec("./colors/lena_condec.jpeg");

  int width = lenaCondec.width();
  int height = lenaCondec.height();

  // enhancing contrast
  float minIntensity = 1.0f;
  float maxIntensity = 0.0f;
  cimg_library::CImg<float> imgBuffer = lenaCondec.get_RGBtoHSI();
  for (int row = 0; row < height; row++)
        for (int col = 0; col < width; col++) {
            const auto I = imgBuffer(col, row, 0, 2);
            minIntensity = std::min((float)I, minIntensity);
            maxIntensity = std::max((float)I, maxIntensity);
        }

  for (int row = 0; row < height; row++)
        for (int col = 0; col < width; col++) {
          auto I = imgBuffer(col, row, 0, 2);
          const auto newIntensity = (((float)I - minIntensity) / (maxIntensity - minIntensity));
          std::cout << "old Intensity " << (float)I << std::endl;

          imgBuffer(col, row, 0, 2) = newIntensity;
          I = imgBuffer(col, row, 0, 2);
          std::cout << "new Intensity " << (float)I << std::endl;
        }

  std::cout << "min " << minIntensity << std::endl;
  std::cout << "max " << maxIntensity << std::endl;

  cimg_library::CImg<float> outputImg = imgBuffer.get_HSItoRGB();

  // Debugging
  outputImg.save_jpeg("./colors/output-image.jpeg");

  std::getchar();

  return 0;
}

I have a repo for this here .我在这里有一个回购。 Make sure you're in the "so-question" branch.确保您在“so-question”分支中。
Note: I modified line 389 of CImg.h from #include <X11/Xlib.h> -> #include "X11/Xlib.h"注意:我从#include <X11/Xlib.h> -> #include "X11/Xlib.h"修改了 CImg.h 的第 389 行

The algorithm above scales the image into [0, 1] range.上面的算法将图像缩放到[0, 1]范围内。
Namely the pixels with the lowest values will be mapped to 0 and the pixels with highest values will be mapped to 1.即具有最低值的像素将被映射到 0,而具有最高值的像素将被映射到 1。

You need to apply thin on RGB image which its values are in the range [0, 1] .您需要在其值在[0, 1]范围内的 RGB 图像上应用薄。 You need to apply it per channel.您需要为每个频道应用它。

I think there may be an issue with the built-in JPEG implementation in CImg .我认为CImg中的内置 JPEG 实现可能存在问题。 I found that your code works fine if you save the output file as a PNG instead of a JPEG.我发现如果您将 output 文件保存为 PNG 而不是 JPEG,您的代码可以正常工作。

在此处输入图像描述

Alternatively you can force CImg to use the IJPEG implementation on your Mac with:或者,您可以强制CImg在您的 Mac 上使用 IJPEG 实现:

clang++ $(pkg-config --cflags --libs libjpeg) -std=c++17 -Dcimg_use_jpeg -lm -lpthread -o "main" "main.cpp"

As a pre-requisite, you may need to install pkkconfig and jpeg with homebrew :作为先决条件,您可能需要使用homebrew安装pkkconfigjpeg

brew install jpeg pkgconfig

Note also that, as long as you don't want to use CImg display() , you can avoid needing to put all the paths and switches for X11 on your compilation command by changing your compilation command to this:另请注意,只要您不想使用CImg display() ,您可以通过将编译命令更改为以下内容来避免需要将 X11 的所有路径和开关放在编译命令上:

clang++ -Dcimg_display=0 ...

As you mentioned you might consider other ways of stretching the contrast, I thought I'd add another option where you can do it in RGB colourspace.正如您所提到的,您可能会考虑其他拉伸对比度的方法,我想我会添加另一个选项,您可以在 RGB 色彩空间中进行操作。 If you find the minimum and maximum of the Red channel and stretch the reds, and then do likewise for the other channels, you will introduce a colour cast.如果您找到红色通道的最小值和最大值并拉伸红色,然后对其他通道进行同样的操作,您将引入偏色。 So, an alternative is to find the minimum of all channels and maximum of all channels and then stretch the channels in concert by the same amount.因此,另一种方法是找到所有通道的最小值和所有通道的最大值,然后将通道一起拉伸相同的量。

Effectively, you are stretching the RGB histogram until any of the channels hits 0 or 255. My C++ is a bit clumsy, but it looks something like this:实际上,您正在拉伸 RGB 直方图,直到任何通道达到 0 或 255。我的 C++ 有点笨拙,但看起来像这样:

#include <iostream>
#include "CImg.h"

int main() {
  cimg_library::CImg<unsigned char> img("lena.png");

  int width  = img.width();
  int height = img.height();

  // Find min and max RGB values for whole image
  unsigned char RGBmin = 255;
  unsigned char RGBmax = 0;
  for (int row = 0; row < height; row++) {
      for (int col = 0; col < width; col++) {
          const auto R = img(col, row, 0, 0);
          const auto G = img(col, row, 0, 1);
          const auto B = img(col, row, 0, 2);
          RGBmin = std::min({R,G,B,RGBmin});
          RGBmax = std::max({R,G,B,RGBmax});
      }
  }

  std::cout << "RGBmin=" << int(RGBmin) << ", RGBmax=" << int(RGBmax) << std::endl;

  // Stretch contrast equally for all channels
  for (int row = 0; row < height; row++) {
      for (int col = 0; col < width; col++) {
          for (int chan = 0; chan <=3; chan++) {
              const auto x = img(col, row, 0, chan);
              const auto newVal = 255*((float)x - RGBmin) / (RGBmax - RGBmin);
              img(col, row, 0, chan) = (unsigned char)newVal;
          }
      }
  }

  // Debugging
  img.save("result2.png");
}

在此处输入图像描述

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM