创建一条曲线,分别调整加载图像的对比度和亮度

2023-12-01

我有一系列图像,想知道是否有可能用 python 编写一些东西来应用对比度和亮度曲线,如下图所示。

enter image description here. enter image description here


正如 Fred 在评论中所述,您可能希望根据您的点创建 Catmull-Rom 样条线,然后使用 OpenCV 中的 LUT 进行应用。

#!/usr/bin/env python3

# from https://splines.readthedocs.io/en/latest/euclidean/piecewise-monotone.html#Examples

import matplotlib.pyplot as plt
import numpy as np
import splines
import cv2

# Just helper code for plotting - you don't need this
def grid_lines(x=None, y=None, ax=None):
    if ax is None:
        ax = plt.gca()
    if x is not None:
        ax.set_xticks(x)
        ax.xaxis.grid(True)
    if y is not None:
        ax.set_yticks(y)
        ax.yaxis.grid(True)
    ax.spines['top'].set_visible(False)
    ax.spines['right'].set_visible(False)
    ax.spines['bottom'].set_visible(False)
    ax.spines['left'].set_visible(False)
    ax.xaxis.set_ticks_position('none')
    ax.yaxis.set_ticks_position('none')

# Just helper code for plotting - you don't need this
def plot_spline_1d(spline, samples=100, **kwargs):
    'Plot a one-dimensional spline.'
    ax = plt.gca()
    times = np.linspace(spline.grid[0], spline.grid[-1], samples)
    ax.plot(times, spline.evaluate(times), **kwargs)
    ax.scatter(spline.grid, spline.evaluate(spline.grid))

下面模拟了类似于你的5个点的S形对比曲线:

xvals = 0, 64, 128, 192, 255
yvals = 0, 32, 128, 206, 255

# Just code for plotting the curve - you don't need this
plot_spline_1d(splines.CatmullRom(yvals, xvals), label='Catmull–Rom')
plt.legend()
grid_lines(xvals)
plt.show()

enter image description here

您需要的实际代码仅从这里开始:

# Derive Catmull-Rom spline for our X,Y
res = splines.CatmullRom(yvals, xvals)

# Make LUT (Lookup Table) from spline
LUT = np.uint8(res.evaluate(range(0,256)))

# Load ramp image as greyscale
im = cv2.imread('ramp.png', cv2.IMREAD_GRAYSCALE)

# Apply LUT to image
stretched = cv2.LUT(im, LUT)

# Save result
cv2.imwrite('result.png', stretched)

这使得这个坡道转动:

enter image description here

进入这个:

enter image description here

请注意,我人为地添加了一个红色细边框,以便您可以在 Stack Overflow 上看到令人讨厌的背景上的图像范围。


关于读取 Photoshop 曲线文件(ACV 或.acv),我不久前写了一些解析它们的代码,但我没有将其与上面的代码集成 - 它应该不会太难 - 你基本上保存 ACV 文件中的点并使用它们生成样条曲线上面的代码。我把它留在下面供有兴趣的人玩:

"""
################################################################################
fauxtoshop - does some things like Adobe Photoshop

Mark Setchell ([email protected])

Reads, interprets and possibly applies Photoshop files:

- Curves files (*.acv)
- Levels files (*.alv)
- Filter Kernel files (*.acf)
- Hue Saturation files (*.ahu)
################################################################################
"""

import sys
import numpy
from struct import unpack

def loadFilter(filename):

    if filename.lower().endswith('.acv'):
        loadCurvesFilter(filename)
        return

    if filename.lower().endswith('.alv'):
        loadLevelsFilter(filename)
        return

    if filename.lower().endswith('.acf'):
        loadKernelFilter(filename)
        return

    if filename.lower().endswith('.ahu'):
        loadHSLFilter(filename)
        return

    sys.exit(f'ERROR: Unknown file extension {filename}')

def loadCurvesFilter(filename):

    with open(filename, 'rb') as f:
       version, ncurves = unpack('>HH', f.read(4))
       print(f'File: {filename}')
       print(f'Version: {version}')
       if version != 4:
          sys.exit('ERROR: Cowardly refusing to read version other than 4')
       print(f'Curve count: {ncurves}')
       curves = []
       for c in range(ncurves):
          npoints, = unpack('>H', f.read(2))
          print(f'Curve: {c}, {npoints} points follow:')
          curve = []
          for p in range(npoints):
             y, x = unpack('>HH', f.read(4))
             print(f'Curve: {c}, point: {p}, x={x}, y={y}')
             curve.append((x,y))
          curves.append(curve)
    return curves

def loadLevelsFilter(filename):
    sys.exit("ERROR: Levels filter not yet implemeted")

def loadKernelFilter(filename):
    sys.exit("ERROR: Kernel filter not yet implemeted")

def loadHSLFilter(filename):

    with open(filename, 'rb') as f:
       version, usage, pad = unpack('>HBB', f.read(4))
       print(f'File: {filename}')
       print(f'Version: {version}')
       if version != 2:
          sys.exit('ERROR: Cowardly refusing to read version other than 2')
       if usage == 0:
           print('Usage: Hue adjustment')
       else:
           print('Usage: Colorization')
           sys.exit(f'ERROR: Cowardly refusing to apply colorization rather than Hue adjustment')
       MasterHue, MasterSaturation, MasterLightness = unpack('>HHH', f.read(6))
       print(f'Master Hue: {MasterHue}')
       print(f'Master Saturation: {MasterSaturation}')
       print(f'Master Lightness: {MasterLightness}')
       # There follow 6 hextants, each with 4 range values and 3 settings values
       for h in range(6):
           ranges = unpack('>HHHH',f.read(8))
           settings = unpack('>HHH', f.read(6))
           print(f'Hextant: {h}, ranges: {ranges}, settings: {settings}')
           
################################################################################
# main
################################################################################
if __name__ == '__main__':

   if len(sys.argv) not in set([2,3]):
      print('Usage: {sys.argv[0]} filter.[acv|ahu|alv|acf] [image]', file=sys.stderr)
      sys.exit(1)

   if len(sys.argv) == 2:
      loadFilter(sys.argv[1])

另请注意,您可以使用以下命令应用 Photoshop 曲线 (ACV) 文件ffmpeg像这样:

ffmpeg -i input.jpg -vf curves=psfile="curves.acv" output.jpg 
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

创建一条曲线,分别调整加载图像的对比度和亮度 的相关文章

随机推荐