# Help manipulating color levels

**URL:** <https://forum.opencv.org/t/help-manipulating-color-levels/2468>\
**Category:** Python\
**Tags:** numpy, imgproc, core\
**Created:** [March 30, 2021, 12:18am UTC](https://forum.opencv.org/t/help-manipulating-color-levels/2468 "2021-03-30T00:18:28Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![xrstokes](https://avatars.discourse-cdn.com/v4/letter/x/7ba0ec/32.png) [@xrstokes](https://forum.opencv.org/u/xrstokes)\
**Post date:** [March 30, 2021, 12:18am UTC](https://forum.opencv.org/t/help-manipulating-color-levels/2468/1 "2021-03-30T00:18:28Z")

</div>

Hi, I’m trying to filter an image that has a lot of over exposed reflective surfaces. It helps if i can lower the color levels after equalizing the histogram. It helps to show the color of the surface suffering the reflection. Here is some code i found on stack exchange that lowers the color levels and achieves the correct effect. But this code is way to slow on my raspberry pi. Is there a way i can get a similar effect using open cv that is quicker. Thanks in advance.

# Adjust Color Levels lower

inBlack = np.array([0, 0, 0], dtype=np.float32)  
inWhite = np.array([255, 255, 255], dtype=np.float32)  
inGamma = np.array([0.5, 0.5, 0.5], dtype=np.float32)  
outBlack = np.array([0, 0, 0], dtype=np.float32)  
outWhite = np.array([255, 255, 255], dtype=np.float32)

img = np.uint8(frame)

img = np.clip((img - inBlack) / (inWhite - inBlack), 0, 255)  
img = (img \*\* (1/inGamma)) \* (outWhite - outBlack) + outBlack  
img = np.clip(img, 0, 255).astype(np.uint8)

cv2.imshow(“test\_1”, img)

---

<div class="post-metadata">

**Author:** ![crackwitz](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.opencv.org/crackwitz/32/14_2.png) [@crackwitz](https://forum.opencv.org/u/crackwitz)\
**Post date:** [March 30, 2021, 11:16am UTC](https://forum.opencv.org/t/help-manipulating-color-levels/2468/2 "2021-03-30T11:16:08Z")

</div>

nevermind, you are asking about optimization…

well, this is numpy, it’ll run fast enough as it is.

all operations have equivalents in pure OpenCV.

if you need optimization, consider getting into how the raspi’s GPU works. you might have to write some kind of shader (OpenGL) or kernel (OpenCL, no idea whether that works on raspis these days).

---

<div class="post-metadata">

**Author:** ![kbarni](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.opencv.org/kbarni/32/26_2.png) [@kbarni](https://forum.opencv.org/u/kbarni)\
**Post date:** [March 30, 2021, 12:36pm UTC](https://forum.opencv.org/t/help-manipulating-color-levels/2468/3 "2021-03-30T12:36:52Z")

</div>

Yep, optimisation is a tricky thing in Python. Especially on a simple computer like the Raspberry Pi.

First, consider to use _integer operations_ where possible instead of _float32_. They are much faster.

An important drawback of Python is that it’s single-threaded - so it will use only one of the four cores of the CPU. _C++ is much faster and it’s easier to parallelize_ (e.g. using TBB library).

These solutions are probably simpler to implement than an OpenGL shader. The Raspberry Pi has no OpenCL support.

---

<div class="post-metadata">

**Author:** ![crackwitz](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.opencv.org/crackwitz/32/14_2.png) [@crackwitz](https://forum.opencv.org/u/crackwitz)\
**Post date:** [March 30, 2021, 3:07pm UTC](https://forum.opencv.org/t/help-manipulating-color-levels/2468/4 "2021-03-30T15:07:58Z")

</div>

> [@kbarni](#):
>
> An important drawback of Python is that it’s single-threaded - so it will use only one of the four cores of the CPU. _C++ is much faster and it’s easier to parallelize_ (e.g. using TBB library).

nobody in their right mind _implements_ numerical algorithms in python (except as a proof of concept). you’re supposed to _use_ libraries like numpy because they implement the stuff in C/C++.

numpy also uses OpenBLAS or Intel MKL for a lot of the heavy lifting. and those ARE multithreaded (yes, “even” when used from python).

raspberry pi 4 doesn’t (yet?) have OpenCL support. the 3B _does_ have some support, and a bunch of caveats (“memory-access speed”)

- [OpenCL on the VideoCore IV! - Raspberry Pi Forums](https://www.raspberrypi.org/forums/viewtopic.php?f=67&t=194952)
- [Running OpenCL On A Raspberry Pi GPU | Hackaday](https://hackaday.com/2019/01/24/running-opencl-on-a-raspberry-pi-gpu/)
- [Install OpenCL on Raspberry Pi 3 B+ - Q-engineering](https://qengineering.eu/install-opencl-on-raspberry-pi-3.html)

---

<div class="post-metadata">

**Author:** ![kbarni](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.opencv.org/kbarni/32/26_2.png) [@kbarni](https://forum.opencv.org/u/kbarni)\
**Post date:** [March 30, 2021, 3:41pm UTC](https://forum.opencv.org/t/help-manipulating-color-levels/2468/5 "2021-03-30T15:41:33Z")

</div>

I’m pretty sure that Numpy is single-threaded on the Raspberry Pi. I’m developing a project on latest Raspbian (using official Numpy packages), and it definitely runs on a single core. If somebody knows how to enable multiprocessing, I’m really interested.

About OpenCL: I wouldn’t wholeheartedly recommend an experimental implementation of this library. OpenCL is quite hard to debug.

---

<div class="post-metadata">

**Author:** ![crackwitz](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.opencv.org/crackwitz/32/14_2.png) [@crackwitz](https://forum.opencv.org/u/crackwitz)\
**Post date:** [March 30, 2021, 5:27pm UTC](https://forum.opencv.org/t/help-manipulating-color-levels/2468/6 "2021-03-30T17:27:06Z")

</div>

numpy uses OpenBLAS/MKL for some of its functions, but not all. you can [check](https://stackoverflow.com/questions/5260068/multithreaded-blas-in-python-numpy) if it can use multi-threading:

```python
N = 2**13; A = np.random.random((N,N)); B = np.random.random((N,N)); C = np.dot(A, B)

```

that keeps my 2012-era quadcore busy on all cores for a handful of seconds (Intel MKL I think). use `2**14` to keep a Ryzen 3900X busy for a handful of seconds (OpenBLAS).

if it does that, but your required functions are still single-threading, that might be a failing of numpy or the functions simply don’t run long enough to engage the multithreading.

I absolutely see that numpy has downsides in a lot of situations (lots of quick calls) but it’s not generally incapable.

---

<div class="post-metadata">

**Author:** ![kbarni](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.opencv.org/kbarni/32/26_2.png) [@kbarni](https://forum.opencv.org/u/kbarni)\
**Post date:** [March 31, 2021, 9:28am UTC](https://forum.opencv.org/t/help-manipulating-color-levels/2468/7 "2021-03-31T09:28:10Z")

</div>

Thanks for the tip! Unfortunately it just confirms my previous post. Numpy runs multithreaded on my laptop, but it’s single-threaded on a Raspberry Pi with Raspbian (didn’t check with other OS).

So I maintain my previous advices:

- Use integer matrices (images) instead of float32
- Implement your code in C++ with TBB parallelization (see [this answer](https://answers.opencv.org/question/90333/parallel-implementation-of-per-pixel-calculations/#90350) on how to do it)

Both methods will give a ~2-4 times speedup.
