如何在 Python-Fu 中执行与 Gimp 的颜色、自动、白平衡等效的操作?
How do I do the equivalent of Gimp's Colors, Auto, White Balance in Python-Fu?
我能找到的唯一函数是:gimp-color-balance,它采用适用的参数:preserve-lum(osity)、cyan-red、magenta-green 和 yellow-blue.
我不确定要为这些参数传递什么值来复制标题中的菜单选项。
根据我在快速查看源代码(并或多或少通过测试图像确认)后的理解,这些是不相关的并且在幕后,Colors>Auto>White Balance
:
- 获取每个通道的直方图
- 获取决定底部和顶部 0.6% 的值
- 使用与 "Levels" 非常相似的内部调用,使用这两个值作为黑点和白点来扩展该通道的值范围。
使用合成图像证明:
之前:
之后:
这一切在 Python 中并不难做到。
K,酷。弄清楚如何编写脚本。
喜欢就用吧。对我来说没问题。
根据GIMP doc,我们需要丢弃红色、绿色和蓝色直方图每一端的像素颜色,这些颜色仅被图像中 0.05% 的像素使用,并尽可能多地拉伸剩余范围尽可能 (Python 代码):
import numpy as np
import cv2 # opencv-python
import matplotlib.pyplot as plt
img = cv2.imread('test.jpg')
x = []
# get histogram for each channel
for i in cv2.split(img):
hist, bins = np.histogram(i, 256, (0, 256))
# discard colors at each end of the histogram which are used by only 0.05%
tmp = np.where(hist > hist.sum() * 0.0005)[0]
i_min = tmp.min()
i_max = tmp.max()
# stretch hist
tmp = (i.astype(np.int32) - i_min) / (i_max - i_min) * 255
tmp = np.clip(tmp, 0, 255)
x.append(tmp.astype(np.uint8))
# combine image back and show it
s = np.dstack(x)
plt.imshow(s[::,::,::-1])
结果与 GIMP 'Colors -> Auto -> White Balance'
后的结果完全相同
UPD: 我们需要 np.clip()
因为 OpenCV
和 numpy
不同地将 int32 转换为 uint8:
# Numpy
np.array([-10, 260]).astype(np.uint8)
>>> array([246, 4], dtype=uint8)
# but we need just [0, 255]
为了完成@banderlog013的回答,我认为Gimp Doc指定首先丢弃每个通道的结束像素,然后拉伸剩余范围。我相信正确的代码是:
img = cv2.imread('test.jpg')
balanced_img = np.zeros_like(img) #Initialize final image
for i in range(3): #i stands for the channel index
hist, bins = np.histogram(img[..., i].ravel(), 256, (0, 256))
bmin = np.min(np.where(hist>(hist.sum()*0.0005)))
bmax = np.max(np.where(hist>(hist.sum()*0.0005)))
balanced_img[...,i] = np.clip(img[...,i], bmin, bmax)
balanced_img[...,i] = (balanced_img[...,i]-bmin) / (bmax - bmin) * 255
我用它取得了不错的效果,试试吧!
如何从本质上获得与 GIMP 的 Colors --> Auto --> White Balance
功能等效的功能:
测试于 Ubuntu 20.04.
从我的 eRCaGuy_hello_world repo here: python/auto_white_balance_img.py 下载以下代码。
安装依赖项:
pip3 install opencv-python # for cv2
pip3 install numpy
现在这里有一些功能齐全的代码,不像这里的其他一些答案是片段并且缺少 import
语句之类的东西。我是从 , and .
借来的
创建文件auto_white_balance_img.py:
#!/usr/bin/python3
import cv2
import numpy as np
file_in = 'test.jpg'
file_in_base = file_in[:-4] # strip file extension
file_in_extension = file_in[-4:]
img = cv2.imread(file_in)
# From @banderlog013's answer:
x = []
# get histogram for each channel
for i in cv2.split(img):
hist, bins = np.histogram(i, 256, (0, 256))
# discard colors at each end of the histogram which are used by only 0.05%
img_out1 = np.where(hist > hist.sum() * 0.0005)[0]
i_min = img_out1.min()
i_max = img_out1.max()
# stretch hist
img_out1 = (i.astype(np.int32) - i_min) / (i_max - i_min) * 255
img_out1 = np.clip(img_out1, 0, 255)
x.append(img_out1.astype(np.uint8))
# From @Canette Ouverture's answer:
img_out2 = np.zeros_like(img) # Initialize final image
for channel_index in range(3):
hist, bins = np.histogram(img[..., channel_index].ravel(), 256, (0, 256))
bmin = np.min(np.where(hist>(hist.sum()*0.0005)))
bmax = np.max(np.where(hist>(hist.sum()*0.0005)))
img_out2[...,channel_index] = np.clip(img[...,channel_index], bmin, bmax)
img_out2[...,channel_index] = ((img_out2[...,channel_index]-bmin) /
(bmax - bmin) * 255)
# Write new files
cv2.imwrite(file_in_base + '_out1' + file_in_extension, img_out1)
cv2.imwrite(file_in_base + '_out2' + file_in_extension, img_out2)
使auto_white_balance_img.py可执行:
chmod +x auto_white_balance_img.py
现在将上面文件中的 file_in
变量设置为您想要的输入图像路径,然后 运行 使用:
python3 auto_white_balance_img.py
# OR
./auto_white_balance_img.py
假设你设置了file_in = 'test.jpg'
,它会产生这两个文件:
test_out1.jpg
# 来自 的结果
test_out2.jpg
# 来自 的结果
我用这个功能来自动白平衡图像。与 Gimp 函数不同,它不会标准化图像对比度。所以它对低对比度图像也很有用。
import numpy as np
from imageio import imread
import matplotlib.pyplot as plt
def auto_white_balance(im, p=.6):
'''Stretch each channel histogram to same percentile as mean.'''
# get mean values
p0, p1 = np.percentile(im, p), np.percentile(im, 100-p)
for i in range(3):
ch = im[:,:,i]
# get channel values
pc0, pc1 = np.percentile(ch, p), np.percentile(ch, 100-p)
# stretch channel to same range as mean
ch = (p1 - p0) * (ch - pc0) / (pc1 - pc0) + p0
im[:,:,i] = ch
return im
def test():
im = imread('imageio:astronaut.png')
# distort white balance
im[:,:,0] = im[:,:,0] *.6
im[:,:,1] = im[:,:,1] *.8
plt.imshow(im)
plt.show()
im2 = auto_white_balance(im)
im2 = np.clip(im2, 0, 255) # or 0, 1 for float images
plt.imshow(im2)
plt.show()
if __name__ == "__main__":
test()
如果您想要等效的 Gimp 函数,请改用固定值:
p0, p1 = 0, 255
我能找到的唯一函数是:gimp-color-balance,它采用适用的参数:preserve-lum(osity)、cyan-red、magenta-green 和 yellow-blue.
我不确定要为这些参数传递什么值来复制标题中的菜单选项。
根据我在快速查看源代码(并或多或少通过测试图像确认)后的理解,这些是不相关的并且在幕后,Colors>Auto>White Balance
:
- 获取每个通道的直方图
- 获取决定底部和顶部 0.6% 的值
- 使用与 "Levels" 非常相似的内部调用,使用这两个值作为黑点和白点来扩展该通道的值范围。
使用合成图像证明:
之前:
之后:
这一切在 Python 中并不难做到。
K,酷。弄清楚如何编写脚本。
喜欢就用吧。对我来说没问题。
根据GIMP doc,我们需要丢弃红色、绿色和蓝色直方图每一端的像素颜色,这些颜色仅被图像中 0.05% 的像素使用,并尽可能多地拉伸剩余范围尽可能 (Python 代码):
import numpy as np
import cv2 # opencv-python
import matplotlib.pyplot as plt
img = cv2.imread('test.jpg')
x = []
# get histogram for each channel
for i in cv2.split(img):
hist, bins = np.histogram(i, 256, (0, 256))
# discard colors at each end of the histogram which are used by only 0.05%
tmp = np.where(hist > hist.sum() * 0.0005)[0]
i_min = tmp.min()
i_max = tmp.max()
# stretch hist
tmp = (i.astype(np.int32) - i_min) / (i_max - i_min) * 255
tmp = np.clip(tmp, 0, 255)
x.append(tmp.astype(np.uint8))
# combine image back and show it
s = np.dstack(x)
plt.imshow(s[::,::,::-1])
结果与 GIMP 'Colors -> Auto -> White Balance'
后的结果完全相同UPD: 我们需要 np.clip()
因为 OpenCV
和 numpy
不同地将 int32 转换为 uint8:
# Numpy
np.array([-10, 260]).astype(np.uint8)
>>> array([246, 4], dtype=uint8)
# but we need just [0, 255]
为了完成@banderlog013的回答,我认为Gimp Doc指定首先丢弃每个通道的结束像素,然后拉伸剩余范围。我相信正确的代码是:
img = cv2.imread('test.jpg')
balanced_img = np.zeros_like(img) #Initialize final image
for i in range(3): #i stands for the channel index
hist, bins = np.histogram(img[..., i].ravel(), 256, (0, 256))
bmin = np.min(np.where(hist>(hist.sum()*0.0005)))
bmax = np.max(np.where(hist>(hist.sum()*0.0005)))
balanced_img[...,i] = np.clip(img[...,i], bmin, bmax)
balanced_img[...,i] = (balanced_img[...,i]-bmin) / (bmax - bmin) * 255
我用它取得了不错的效果,试试吧!
如何从本质上获得与 GIMP 的 Colors --> Auto --> White Balance
功能等效的功能:
测试于 Ubuntu 20.04.
从我的 eRCaGuy_hello_world repo here: python/auto_white_balance_img.py 下载以下代码。
安装依赖项:
pip3 install opencv-python # for cv2
pip3 install numpy
现在这里有一些功能齐全的代码,不像这里的其他一些答案是片段并且缺少 import
语句之类的东西。我是从
创建文件auto_white_balance_img.py:
#!/usr/bin/python3
import cv2
import numpy as np
file_in = 'test.jpg'
file_in_base = file_in[:-4] # strip file extension
file_in_extension = file_in[-4:]
img = cv2.imread(file_in)
# From @banderlog013's answer:
x = []
# get histogram for each channel
for i in cv2.split(img):
hist, bins = np.histogram(i, 256, (0, 256))
# discard colors at each end of the histogram which are used by only 0.05%
img_out1 = np.where(hist > hist.sum() * 0.0005)[0]
i_min = img_out1.min()
i_max = img_out1.max()
# stretch hist
img_out1 = (i.astype(np.int32) - i_min) / (i_max - i_min) * 255
img_out1 = np.clip(img_out1, 0, 255)
x.append(img_out1.astype(np.uint8))
# From @Canette Ouverture's answer:
img_out2 = np.zeros_like(img) # Initialize final image
for channel_index in range(3):
hist, bins = np.histogram(img[..., channel_index].ravel(), 256, (0, 256))
bmin = np.min(np.where(hist>(hist.sum()*0.0005)))
bmax = np.max(np.where(hist>(hist.sum()*0.0005)))
img_out2[...,channel_index] = np.clip(img[...,channel_index], bmin, bmax)
img_out2[...,channel_index] = ((img_out2[...,channel_index]-bmin) /
(bmax - bmin) * 255)
# Write new files
cv2.imwrite(file_in_base + '_out1' + file_in_extension, img_out1)
cv2.imwrite(file_in_base + '_out2' + file_in_extension, img_out2)
使auto_white_balance_img.py可执行:
chmod +x auto_white_balance_img.py
现在将上面文件中的 file_in
变量设置为您想要的输入图像路径,然后 运行 使用:
python3 auto_white_balance_img.py
# OR
./auto_white_balance_img.py
假设你设置了file_in = 'test.jpg'
,它会产生这两个文件:
test_out1.jpg
# 来自 的结果
test_out2.jpg
# 来自 的结果
我用这个功能来自动白平衡图像。与 Gimp 函数不同,它不会标准化图像对比度。所以它对低对比度图像也很有用。
import numpy as np
from imageio import imread
import matplotlib.pyplot as plt
def auto_white_balance(im, p=.6):
'''Stretch each channel histogram to same percentile as mean.'''
# get mean values
p0, p1 = np.percentile(im, p), np.percentile(im, 100-p)
for i in range(3):
ch = im[:,:,i]
# get channel values
pc0, pc1 = np.percentile(ch, p), np.percentile(ch, 100-p)
# stretch channel to same range as mean
ch = (p1 - p0) * (ch - pc0) / (pc1 - pc0) + p0
im[:,:,i] = ch
return im
def test():
im = imread('imageio:astronaut.png')
# distort white balance
im[:,:,0] = im[:,:,0] *.6
im[:,:,1] = im[:,:,1] *.8
plt.imshow(im)
plt.show()
im2 = auto_white_balance(im)
im2 = np.clip(im2, 0, 255) # or 0, 1 for float images
plt.imshow(im2)
plt.show()
if __name__ == "__main__":
test()
如果您想要等效的 Gimp 函数,请改用固定值: p0, p1 = 0, 255