`yuv2gray()` / `luv2gray()` (and other yuv2* / luv2* conversions) seem to ignore the intermediate BGR conversion. Is this intended?
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 817
- Forks
- 110
- PR merge metrics
- No merged PRs in 30d
Description
I checked the documentation and searched the repository for the relevant color-conversion behavior. I could not find any documentation or existing implementation pattern indicating that these conversions are intentionally performed directly on the original YUV/LUV values.
Please confirm you have the latest versions of caer, numpy, opencv-contrib-python, and h5py prior to reporting a bug (delete one): YES (caer from dev, latest numpy and opencv-contrib-python from PyPI.)
Describe the bug
Hi! While reading caer/color/_yuv.py I noticed something that looks like a bug, but I'd like to confirm it's not intended before opening a PR.
The derived conversions compute a BGR intermediate and then discard it, converting the original YUV array as if it were BGR:
# caer/color/_yuv.py, yuv2gray()
img = yuv2bgr(tens)
img = bgr2gray(tens) # <- uses `tens` (YUV data), not `img` (BGR)
return to_tensor(img, cspace="gray")
The same pattern appears in yuv2hls, yuv2hsv, yuv2lab, yuv2luv and, in caer/color/_luv.py, in luv2gray, luv2hls, luv2hsv, luv2lab, luv2yuv. Since caer.to_gray(), to_hsv(), to_hls(), to_lab(), to_yuv() and to_luv() call these functions, they are affected too for YUV/LUV inputs.
For comparison, caer/color/_hsv.py does pass the intermediate along (bgr = hsv2bgr(tens), then img = bgr2gray(bgr)), and its results match OpenCV.
To Reproduce
This uses the bundled sunrise image, so no external files are needed:
import cv2 as cv
import numpy as np
import caer
bgr = caer.data.sunrise(rgb=False)
# YUV -> Grayscale
yuv = caer.to_tensor(cv.cvtColor(bgr, cv.COLOR_BGR2YUV), cspace="yuv")
expected = cv.cvtColor(cv.cvtColor(yuv, cv.COLOR_YUV2BGR), cv.COLOR_BGR2GRAY)
print("yuv2gray matches OpenCV:", np.array_equal(caer.yuv2gray(yuv), expected))
print("to_gray(yuv) matches OpenCV:", np.array_equal(caer.to_gray(yuv), expected))
print("yuv2gray equals bgr2gray on the raw YUV data:", np.array_equal(caer.yuv2gray(yuv), caer.bgr2gray(yuv)))
# HSV -> Grayscale, for comparison
hsv = caer.to_tensor(cv.cvtColor(bgr, cv.COLOR_BGR2HSV), cspace="hsv")
expected = cv.cvtColor(cv.cvtColor(hsv, cv.COLOR_HSV2BGR), cv.COLOR_BGR2GRAY)
print("hsv2gray matches OpenCV:", np.array_equal(caer.hsv2gray(hsv), expected))
Output:
yuv2gray matches OpenCV: False
to_gray(yuv) matches OpenCV: False
yuv2gray equals bgr2gray on the raw YUV data: True
hsv2gray matches OpenCV: True
Expected behavior
yuv2gray(yuv) should equal converting YUV -> BGR -> Gray (as hsv2gray does for HSV). Instead it equals bgr2gray applied directly to the YUV values. The same applies to the other nine functions listed above.
Error with full stack trace
No exception is raised; the functions return silently wrong pixel values.
Additional context
- caer:
devbranch atc313af56(version 2.1.1) - Python: 3.12.12
- numpy: 2.5.3
- opencv-contrib-python: 5.0.0
- OS: Linux (Fedora 43, x86_64)
The existing tests in tests/color/test_yuv.py and tests/color/test_luv.py only check the shape and the cspace flag, which is probably why this wasn't caught.
If this is indeed unintended, I'd be happy to open a PR against dev with the fix (passing img instead of tens in those 10 places) and tests that compare the results against OpenCV.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in caer/color/_yuv.py and caer/color/_luv.py, comparing their derived conversions with the intermediate-passing pattern in caer/color/_hsv.py. Run the bundled sunrise reproduction, then inspect tests/color/test_yuv.py and tests/color/test_luv.py. Done means the listed YUV/LUV conversions match the corresponding OpenCV conversions, with tests covering pixel values as well as shape and cspace.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- opencv, python
- Domain
- computer-vision
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 85/100