New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix rounding error on RGB to L conversion #4320
Fix rounding error on RGB to L conversion #4320
Conversation
This code was altered by me but I believe the error was there from the beginning. I think this PR is relatively safe for merge in 7.0.0. A bit more work needs for fixing other |
Looks like you're solving the second problem in the thread, but the original poster would like our results to exactly match OpenCV. This PR brings Pillow closer, but doesn't exactly match it. |
We don't have an aim "to do everything like OpenCV". The real aim is to do everything correctly and OpenCV is wrong very often. from PIL import Image
import cv2, numpy
im = Image.open('../imgs/56811035-ce7e0000-6805-11e9-9123-b297635e739e.png')
num_im = numpy.array(im)
ref = (num_im[:, :, 0] * 0.299 + num_im[:, :, 1] * 0.587 + num_im[:, :, 2] * 0.114 + 0.5).astype('uint8')
res_pillow = numpy.array(im.convert('L'))
res_cv2 = cv2.cvtColor(num_im, cv2.COLOR_RGB2GRAY)
print(numpy.count_nonzero(ref - res_pillow))
print(numpy.count_nonzero(ref - res_cv2))
So Pillow's result much closer to reference. I think this is because OpenCV uses fewer significant bits. Anyway, now this is a question of precision, not rounding error which was truly an error. |
@@ -44,7 +44,8 @@ | |||
#define L(rgb)\ | |||
((INT32) (rgb)[0]*299 + (INT32) (rgb)[1]*587 + (INT32) (rgb)[2]*114) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you've changed ImageColor, shouldn't this be changed as well for consistency?
Line 137 in fa1deca
color = (r * 299 + g * 587 + b * 114 + 500) // 1000 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not the "L" macro itself should be fixed. This macro is used for F mode for example, where no rounding needed. Instead, every place where "L" is used should be analyzed. This is a bit more work that needs more attention and I haven't much time today to do this before the release.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, I've fixed ImageColor.getcolor implementation.
Furthermore, an update to Pillow has improved the floating-point precision of the image hash algorithm, requiring minor updates to the respective unit tests. See python-pillow/Pillow#4320
Fixes #3800