且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

在两张图片之间匹配色彩优势的***策略是什么?

更新时间:2023-02-20 13:07:16

我有一些有用的想法-它们有点像从Photoshop开始,然后在Perl,ImageMagick和OpenCV中徘徊.我是 David Fokos

I have some ideas that should be of use - they kind of start in Photoshop and wander through Perl, ImageMagick and OpenCV. I am a big fan of the warm and beautiful tonalities achieved by photographers such as David Fokos and Michael Kenna and I worked out, many years back, how to replicate their toning.

首先,在Photoshop中加载图像,转换为黑白模式,然后返回RGB模式,添加一个Curves调整层和一个带有原始彩色图像的新层.您的图层"窗口将如下所示:

First, load your image up in Photoshop, convert to black and white mode, and then back to RGB mode, add a Curves adjustment layer and a new layer with the original colour image. Your Layers window will look like this:

现在关闭除灰色背景以外的所有图层,并使用颜色滴管"查找并标记:

Now turn off all layers except the grey background, and use the Color Dropper to find and mark:

  • 四分之一像素(即信息"窗口中的值为64左右)
  • 中间色调像素(即信息"窗口中大约为128)
  • 四分之三的像素(即信息"窗口中大约为192)

现在重新打开其他图层,并找到这三种色调在RGB中的映射:

Now turn the other layers back on and find what those three tones map to in RGB:

现在进入曲线"层,并调整红色,绿色和蓝色曲线以匹配这些值:

Now go in the Curves layer and adjust the Red, Green and Blue curves to match those values:

然后如果您切换回RGB,则可以在一张图上看到所有三条曲线:

And if you then switch back to RGB, you can see all three curves on one diagram:

您现在只需要将该Curve保存为扩展名为ACV的文件,即可将其应用于其他图像:

You now just need to save that Curve as a file with ACV extension and you can apply it to other images:

这样做让我有点无聊,所以我写了一个Perl脚本,它完全一样.您将其传递为定调后的图像作为文件名,它会找到四分之一,中四分之三的色调,然后创建一个Adobe Photoshop Curves文件-一个ACV文件,您可以将其批量应用到其他照片上.

I got a bit bored doing that, so I wrote a Perl script that does exactly the same. You pass it a toned image as a filename, it finds the quarter, mid and three-quarter tones and then creates an Adobe Photoshop Curves file - an ACV file for you which you can then batch apply to other photos.

这是Perl:

#!/usr/bin/perl
use strict;
use warnings;
use Image::Magick;
use Data::Dumper;

my $Debug=1;    # 1=print debug messages, 0=don't
my $NPOINTS=5;  # Number of points in curve we create

# Read in image in first parameter
my $imagename=$ARGV[0];
my $orig=Image::Magick::->new;
my $x = $orig->Read($imagename);
  warn "$x" if "$x";

my $width =$orig->Get('columns');
my $height=$orig->Get('rows');
my $depth=$orig->Get('depth');
print "DEBUG: ",$width,"x",$height,", depth: ",$depth,"\n" if $Debug;

# Access pixel cache
my @RGBpixels  = $orig->GetPixels(map=>'RGB',height=>$height,width=>$width,normalize=>1);

my ($i,$j,$p);
my (@greypoint,@Rpoint,@Gpoint,@Bpoint);
for($p=0;$p<$NPOINTS;$p++){
   my $greylevelsought=int(($p+1)*256/($NPOINTS+1));
   my $nearestgrey=1000;
   for(my $t=0;$t<$height*$width;$t++){
         my $R = int(255*$RGBpixels[(3*$t)+0]);
         my $G = int(255*$RGBpixels[(3*$t)+1]);
         my $B = int(255*$RGBpixels[(3*$t)+2]);
         my $this=int(0.21*$R + 0.72*$G +0.07*$B);
         printf "Point: %d, Greysought: %d, this pixel: %d\n",$p,$greylevelsought,$this if $Debug>1;
         if(abs($this-$greylevelsought)<abs($nearestgrey-$greylevelsought)){
            $nearestgrey=$this;
            $greypoint[$p]=$nearestgrey;
            $Rpoint[$p]=$R;
            $Gpoint[$p]=$G;
            $Bpoint[$p]=$B;
         }
   }
   printf "DEBUG: Point#: %d, sought grey: %d, nearest grey: %d\n",$p,$greylevelsought,$nearestgrey if $Debug;
}

# Work out name of the curve file = image basename + acv
my $curvefile=substr($imagename,0,rindex($imagename,'.')) . ".acv";
open(my $out,'>:raw',$curvefile) or die "Unable to open: $!";
print $out pack("s>",4); # Version=4
print $out pack("s>",4); # Number of curves in file = Master NULL curve + R + G + B

print $out pack("s>",2);            # Master NULL curve with 2 points for all channels
print $out pack("s>",0  ),pack("s>",0  );   # 0 out, 0 in
print $out pack("s>",255),pack("s>",255);   # 255 out, 255 in

print $out pack("s>",2+$NPOINTS);       # Red curve
print $out pack("s>",0  ),pack("s>",0  );   # 0 out, 0 in
for($p=0;$p<$NPOINTS;$p++){
   print $out pack("s>",$Rpoint[$p]),pack("s>",$greypoint[$p]);
}
print $out pack("s>",255),pack("s>",255);   # 255 out, 255 in

print $out pack("s>",2+$NPOINTS);       # Green curve
print $out pack("s>",0  ),pack("s>",0  );   # 0 out, 0 in
for($p=0;$p<$NPOINTS;$p++){
   print $out pack("s>",$Gpoint[$p]),pack("s>",$greypoint[$p]);
}
print $out pack("s>",255),pack("s>",255);   # 255 out, 255 in

print $out pack("s>",2+$NPOINTS);       # Blue curve
print $out pack("s>",0  ),pack("s>",0  );    # 0 out, 0 in
for($p=0;$p<$NPOINTS;$p++){
   print $out pack("s>",$Bpoint[$p]),pack("s>",$greypoint[$p]);
}
print $out pack("s>",255),pack("s>",255);    # 255 out, 255 in

close($out);

如果要在OpenCV中执行此操作,则可以非常简单地将脚本的前70%转换为OpenCV-仅2个循环.然后,您将获得四分之一,中点和四分之三的音调.您可以使用诸如gnuplot的曲线拟合程序(我不了解您的技能)将曲线拟合到点,然后为256个值0-255中的每一个生成一个查找表,并将其应用于您的使用cv::LUT()复制或克隆色调的其他图像.

If you want to do this in OpenCV, you could translate the first 70% of the script to OpenCV pretty simply - it is just 2 loops. Then you would have the quarter, mid and three-quarter tone points. You could use a curve-fitting program such as gnuplot (I have no idea of your skillset) to fit a curve to the points and then generate a lookup table for each of the 256 values 0-255, and apply that to your other images using cv::LUT() to replicate or clone the tone.