mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-02-03 13:14:27 +03:00
Merge pull request #4843 from navneeth/master
This commit is contained in:
commit
9c6d0bdcb7
|
@ -1,6 +1,6 @@
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from PIL import Image, ImageOps, features
|
from PIL import Image, ImageDraw, ImageOps, ImageStat, features
|
||||||
|
|
||||||
from .helper import (
|
from .helper import (
|
||||||
assert_image_equal,
|
assert_image_equal,
|
||||||
|
@ -25,7 +25,9 @@ def test_sanity():
|
||||||
ImageOps.autocontrast(hopper("RGB"))
|
ImageOps.autocontrast(hopper("RGB"))
|
||||||
|
|
||||||
ImageOps.autocontrast(hopper("L"), cutoff=10)
|
ImageOps.autocontrast(hopper("L"), cutoff=10)
|
||||||
|
ImageOps.autocontrast(hopper("L"), cutoff=(2, 10))
|
||||||
ImageOps.autocontrast(hopper("L"), ignore=[0, 255])
|
ImageOps.autocontrast(hopper("L"), ignore=[0, 255])
|
||||||
|
ImageOps.autocontrast(hopper("L"), mask=hopper("L"))
|
||||||
|
|
||||||
ImageOps.colorize(hopper("L"), (0, 0, 0), (255, 255, 255))
|
ImageOps.colorize(hopper("L"), (0, 0, 0), (255, 255, 255))
|
||||||
ImageOps.colorize(hopper("L"), "black", "white")
|
ImageOps.colorize(hopper("L"), "black", "white")
|
||||||
|
@ -312,3 +314,51 @@ def test_autocontrast_cutoff():
|
||||||
|
|
||||||
assert autocontrast(10) == autocontrast((10, 10))
|
assert autocontrast(10) == autocontrast((10, 10))
|
||||||
assert autocontrast(10) != autocontrast((1, 10))
|
assert autocontrast(10) != autocontrast((1, 10))
|
||||||
|
|
||||||
|
|
||||||
|
def test_autocontrast_mask_toy_input():
|
||||||
|
# Test the mask argument of autocontrast
|
||||||
|
with Image.open("Tests/images/bw_gradient.png") as img:
|
||||||
|
|
||||||
|
rect_mask = Image.new("L", img.size, 0)
|
||||||
|
draw = ImageDraw.Draw(rect_mask)
|
||||||
|
x0 = img.size[0] // 4
|
||||||
|
y0 = img.size[1] // 4
|
||||||
|
x1 = 3 * img.size[0] // 4
|
||||||
|
y1 = 3 * img.size[1] // 4
|
||||||
|
draw.rectangle((x0, y0, x1, y1), fill=255)
|
||||||
|
|
||||||
|
result = ImageOps.autocontrast(img, mask=rect_mask)
|
||||||
|
result_nomask = ImageOps.autocontrast(img)
|
||||||
|
|
||||||
|
assert result != result_nomask
|
||||||
|
assert ImageStat.Stat(result, mask=rect_mask).median == [127]
|
||||||
|
assert ImageStat.Stat(result_nomask).median == [128]
|
||||||
|
|
||||||
|
|
||||||
|
def test_auto_contrast_mask_real_input():
|
||||||
|
# Test the autocontrast with a rectangular mask
|
||||||
|
with Image.open("Tests/images/iptc.jpg") as img:
|
||||||
|
|
||||||
|
rect_mask = Image.new("L", img.size, 0)
|
||||||
|
draw = ImageDraw.Draw(rect_mask)
|
||||||
|
x0, y0 = img.size[0] // 2, img.size[1] // 2
|
||||||
|
x1, y1 = img.size[0] - 40, img.size[1]
|
||||||
|
draw.rectangle((x0, y0, x1, y1), fill=255)
|
||||||
|
|
||||||
|
result = ImageOps.autocontrast(img, mask=rect_mask)
|
||||||
|
result_nomask = ImageOps.autocontrast(img)
|
||||||
|
|
||||||
|
assert result_nomask != result
|
||||||
|
assert_tuple_approx_equal(
|
||||||
|
ImageStat.Stat(result, mask=rect_mask).median,
|
||||||
|
[195, 202, 184],
|
||||||
|
threshold=2,
|
||||||
|
msg="autocontrast with mask pixel incorrect",
|
||||||
|
)
|
||||||
|
assert_tuple_approx_equal(
|
||||||
|
ImageStat.Stat(result_nomask).median,
|
||||||
|
[119, 106, 79],
|
||||||
|
threshold=2,
|
||||||
|
msg="autocontrast without mask pixel incorrect",
|
||||||
|
)
|
||||||
|
|
|
@ -50,6 +50,14 @@ Add MIME type to PsdImagePlugin
|
||||||
API Additions
|
API Additions
|
||||||
=============
|
=============
|
||||||
|
|
||||||
|
ImageOps.autocontrast: add mask parameter
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
:py:func:`.ImageOps.autocontrast` can now take a ``mask`` parameter:
|
||||||
|
|
||||||
|
* Histogram used in contrast operation is computed using pixels within the mask.
|
||||||
|
If no mask is given the entire image is used for histogram computation.
|
||||||
|
|
||||||
ImageOps.autocontrast cutoffs
|
ImageOps.autocontrast cutoffs
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
|
|
@ -61,10 +61,10 @@ def _lut(image, lut):
|
||||||
# actions
|
# actions
|
||||||
|
|
||||||
|
|
||||||
def autocontrast(image, cutoff=0, ignore=None):
|
def autocontrast(image, cutoff=0, ignore=None, mask=None):
|
||||||
"""
|
"""
|
||||||
Maximize (normalize) image contrast. This function calculates a
|
Maximize (normalize) image contrast. This function calculates a
|
||||||
histogram of the input image, removes ``cutoff`` percent of the
|
histogram of the input image (or mask region), removes ``cutoff`` percent of the
|
||||||
lightest and darkest pixels from the histogram, and remaps the image
|
lightest and darkest pixels from the histogram, and remaps the image
|
||||||
so that the darkest pixel becomes black (0), and the lightest
|
so that the darkest pixel becomes black (0), and the lightest
|
||||||
becomes white (255).
|
becomes white (255).
|
||||||
|
@ -74,9 +74,12 @@ def autocontrast(image, cutoff=0, ignore=None):
|
||||||
high ends. Either a tuple of (low, high), or a single
|
high ends. Either a tuple of (low, high), or a single
|
||||||
number for both.
|
number for both.
|
||||||
:param ignore: The background pixel value (use None for no background).
|
:param ignore: The background pixel value (use None for no background).
|
||||||
|
:param mask: Histogram used in contrast operation is computed using pixels
|
||||||
|
within the mask. If no mask is given the entire image is used
|
||||||
|
for histogram computation.
|
||||||
:return: An image.
|
:return: An image.
|
||||||
"""
|
"""
|
||||||
histogram = image.histogram()
|
histogram = image.histogram(mask)
|
||||||
lut = []
|
lut = []
|
||||||
for layer in range(0, len(histogram), 256):
|
for layer in range(0, len(histogram), 256):
|
||||||
h = histogram[layer : layer + 256]
|
h = histogram[layer : layer + 256]
|
||||||
|
|
Loading…
Reference in New Issue
Block a user