正如 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()
您需要的实际代码仅从这里开始:
# 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)
这使得这个坡道转动:
进入这个:
请注意,我人为地添加了一个红色细边框,以便您可以在 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