awawa-dev / HyperHDR

Highly optimized open source ambient lighting implementation based on modern digital video and audio stream analysis for Windows, macOS and Linux (x86 and Raspberry Pi / ARM).
http://www.hyperhdr.eu/
MIT License
1.05k stars 110 forks source link

Low brightness LED Strip inaccuracies. (black-level threshold in the smoothing algorithm) #180

Closed LMaier-dev closed 2 years ago

LMaier-dev commented 2 years ago

Feature request

What problem does this feature solve?

Theres already the option for Anti-flickering threshold which completely eliminated my flickering issue with low Brightness. Thank you for that! But I hoped this could be extended to have another option for turning the LEDs completely off for very low brightess values. I mean like a black-level threshold which would logically be smaller than the Anti-Flickering one. Because no matter how much time I spend on calibrating the LEDs with gammas (im at ~2.6) there is always either blue, red or green when it should be grey (or very dark brown for example). With that being said I'm very satisfied with the result in brighter scenes, the color is spot on in those cases (also with bright brown or skin colors which are especially bad in low brightness cases). I think its just a LED Strip Problem which could be fixed by that threshold. And since the anti flickering is already implemented the Leds shouldnt flicker when the threshold is crossed multiple times in short sequence.

What does the proposed API look like?

How should this be implemented in your opinion?

In combination with the Anti-Flickering threshold in the smoothing Algorithm.

Are you willing to work on this yourself?

I could try it, but I dont know if the threshold value is a good solution to the problem and I'm an amateur programmer at best.

awawa-dev commented 2 years ago

Hi There is one solution specific for HyperHDR and I think it's enough: custom LUT table where custom minimal threshold could be set (more info on the LUT generator subpage in HyperHDR app). Don't know your setup but usually problems with low brightness color accuracy are related to specific LED strip types and could not be cured in any way with the calibration if the user is sensitive for that problem. That's why I chose RGBW sk6812 that is much, much better than other RGB led strip types in that area.

One important thing if you're referring to anti-flickering filter: make sure that you set anti-flickering timeout to some low level (time in ms) because without it the filter can block indefinitely subtle color changes and it's described in v17 release info: without the timeout reddish RGB(2,1,1) never could become dark grey RGB(1,1,1) and it waits for larger step so can also cause symptoms that you described.

LMaier-dev commented 2 years ago

Hello, thanks for the quick reply especially on a sunday. I had the timeout set to the default 500ms, that shouldnt be the problem, it stays red in longer scenes as well. I also dont think the LUT table will fix my problem. Its the worst with a dark brown for example in the way that it is displayed as red. Lets take rgb(50, 30, 0) for example. If I would set all thresholds to 32 this would now be rgb(50, 0, 0) which is a dark but fully red color. So it would make the inaccuracy worse. At least this happens in the preview. I was searching for a option that would take the average over all 3 channels and if that falls below f.e. 32, turns the pixel off to prevent these inaccurate colors. Maybe I'll really buy these RGBW sk6812 some time in the future, but are you sure the proposed brightness threshold could not eliminate this problem for people that have older apa102, ws2811 etc. strips?

awawa-dev commented 2 years ago

Unfortunately it doesn't work that way: I can't guarantee anything, just as HyperHDR comes without any warranty. I can only offer my experience based on several years of using similar systems. If the alternatives could satisfy me, I would definitely choose them, probably a Philips system, to save a lot of money and development time. We're both sensitive to some of the subtle features of LED systems, but we're a niche. For example: video processing flickering side effect has bothered no one until it's fixed in HyperHDR. So to solve my problem I must diagnose it first and then code it. But I think the issue you report can be solve (if it's solvable at all) with current available options and probably with the LED strip upgrade.

Back to the subject: with the average threshold you lose control over particular color channel so it could affect not only brown or reddish colors, with LUT table you have both minimal threshold & gamma correction for each of channel separately. And I think that you forget about minimal Backlight threshold (with 'Colored backlight' option enabled) in the processing tab. With both minimal threshold & such option enabled it could be processed following way: rgb(50, 30, 0) => minimal LUT threshold => rgb (50, 0, 0) => minimal colored backlight 30 => rgb (50, 30, 30). sk6812 cold RGBW white channel could soften very sharp gradients which is especially visible on low brightness scene starting from RGB >= 2. Unfortunately RGBW "neutral" ("neutral" term is nowhere near the truth, in fact it's yellow) version is more limited due to weaker blue component that we must enhance a bit and it kicks in on bit higher level.

LMaier-dev commented 2 years ago

Of course I know that you dont offer any warranty. Sorry if my message sounded rude. I didn't intend it in that way.

For me these inaccuracies also happen with green colors. Its probably just the strip, but since its for all channels I would want that parameter to affect all the channels at once. Sadly the minimal Backlight threshold also doesn't do exactly what I hoped for. It of course eliminates the red low brightness problems, but at the expense, that there's always backlight even when watching for example a space movie with pitch black scenes. That is also distracting, for me even more so, than just leaving the color inaccuracies. What would be nice if there was a option to choose a static color for the Backlight (in my case i would try using 0,0,0 and setting the Backlight threshold to ~10%).

Thanks again for your answers and time.

awawa-dev commented 2 years ago

No offense taken ;)

What would be nice if there was a option to choose a static color for the Backlight (in my case i would try using 0,0,0 and setting the Backlight threshold to ~10%).

I don't understand that: do you want to cut off all the colors below 10% and set them to black? That's how currently LUT minimal threshold works. But the problem with the minimal threshold is when the color jumps over the lower limit and it causes sudden jump in the LED brightness even with the smoothing enabled. So usually it should be applied to cut off very low values.

To eliminate one color channel dominance, the gamma correction should be used instead. It dumps low values quite well but it affects all the 0-255 range also. So this is tilting at windmills when the problem lies in the LED strip characteristic and it's visible on low brightness (I'm still assuming that the video grabber captures the video without any distortion). I've never succeeded in satisfying calibration for my ws2801 and ws2813: even if I fixed low colors by reducing red or green then the problem of lacking of that color channels appears at the middle and at the high levels. With RGBW sk6812 on the other hand I leave all the calibration settings on default: it just works well out of box (calibration of that RGBW LED strip depends in fact in proper white channel algorithm but it's outside HyperHDR and it's other story).

LMaier-dev commented 2 years ago

Hey again, I was pretty worked up the last days so didnt get to response. The LUT threshold makes the problem actually worse see in the attached Image I set all three thresholds to 30. Since the background is a bluesish grey lets say rgb(25,25,35) NVIDIA_Share_KhgBqlOCQ7 The Background now becomes mostly dark blue even though it should still be grey mostly. But the LUT thresholds see rgb(25,25,35) and just cut off red and green channels and make it to rgb(0,0,35) that is the exact behaviour I mentioned in my second post, where for example blueish but mostly grey colors trigger only the blue LED. But it's not just blue, the other channels react the same to "washed out" colors. Thats why taking the average of this (28,3333) and applying a brightness threshold of f.e. 30 is the only threshold that would make sense to hopefully alleviate that problem.

do you want to cut off all the colors below 10% and set them to black

I don't want to look at channels seperately, because these cheap WS2812b (yes I know Im dumb to have bought those but that was a few years back and I had no clue about their limitations) have no problem controlling single channels. But instead have their limitations having accurate brightness levels across channels. So each channel is behaving differently in bright and dark colors. They are truly the problem in my case, I fully aggree with you. But I still think having this brightness built into the smoothing algorithm in combination with the antiflickering, could fix the color inaccuracies and still prevent:

But the problem with the minimal threshold is when the color jumps over the lower limit and it causes sudden jump in the LED brightness even with the smoothing enabled

So it could have a similar minimal step needed to get the LED back on/off. For example it currently is off because brightness is at 27<30 to be back on it has to be minimum 32 in brightness. On the other hand if it is currently on it has to drop below 28 to be off (and stay off until its back over 32). So a play of +-2 to avoid the flickering around the threshold.

To eliminate one color channel dominance, the gamma correction should be used instead. It dumps low values quite well but it affects all the 0-255 range also.

Thats the reason this doesn't help in the dark scene inaccuracies, it mostly just shifts the inaccuracies further up/down the curve. Because right now I can only get the colors perfect in either bright/medium colors (I prefer that) or dark colors. For these cheap LEDs the only thing that would help (probably), would be multiple points of adjustment in the gamma curve, but I don't think most people would use that (I certainly wouldn't).

This got pretty long, sorry for that I'm not the best with writing. Thanks again for your time, have a nice day/night whatever your time is :)

awawa-dev commented 2 years ago

Hi Personally I gave up for tuning-up calibration of the RGB led strip on the dark scenes and I met that problem 6 years ago when build my first setup with Hyperion using ws2801. I did try but it didn't work with any workaround: there are always some side-effects like another source of induced flickering (when non-continues intervals are used), sudden burst of light when crossing the threshold limit when it's set too high, lack of specific color on the bright scenes because it was dump to fix the low brightness scenes etc.. and then we try to find another workaround for them. That's the road to nowhere. I still have working backup setup of RGB led strip and during testing of HyperHDR it brings that problem/memory back.

Most of the users are fine with the RGB performance, the rest choose RGBW. If there was no good alternative then maybe we could implement some sophisticated and also almost impossible to configure for average mortal (just as you noticed) filters like gamma channel correction divided into level intervals for each channel or constructed with a help of a curve...still with better theoretical effect than high-level threshold and manipulating the smoothing as work-around for its side-effects. It's not only mine or yours idea, I met it years ago.

RGB LED strip have advantages: some of them are much faster than RGBW sk6812, usually are cheaper and almost always colors are more vibrant which is great for bright scenes. But they have one described weakness where RGBW is much better. So I hope you understand I won't back again on that path that I've already tried and it's closed subject for me. In situations like yours I put it on wrong choice of LED strip type that was used to build the particular bias lightning setup... like I did it few times before.

Best regards Awawa

chcore commented 3 months ago

In my setup, bright colors are reasonably accurate but dark-ish ones tend to translate to green or red on the LEDs. This makes it difficult to watch anything with dark scenes (i.e. pretty much everything that is not bright and animated). My next LED purchase will be RGBW as you suggest, but that might have to wait for a TV upgrade.

In the mean time I would like to hack together a software workaround for personal use, similar to what the OP was after. @awawa-dev any pointers as to where I should start (in the code)?

I would like to try and modify the RGB values before they get sent to the LEDS, so that any time the value of R + B + G is less than 30, it is clamped to 0,0,0. It is not likely to fix the problem, but it might be better than what I'm experiencing at the moment.

awawa-dev commented 3 months ago

@chcore Which grabber are you using?

I would like to try and modify the RGB values before they get sent to the LEDS, so that any time the value of R + B + G is less than 30, it is clamped to 0,0,0. It is not likely to fix the problem, but it might be better than what I'm experiencing at the moment.

so when all of R/B/G are less than 30 then clamp it to (0,0,0)? But where: before smoothing or after, just before sending to LED?

chcore commented 3 months ago

@chcore Which grabber are you using?

I am using piccap for WebOS, with HyperHDR running on a Raspberry Pi. Ideally I would be using a software grabber directly on my HTPC, but it is my understanding that it is not possible when using Kodi with GBM rendering on x86.

so when all of R/B/G are less than 30 then clamp it to (0,0,0)? But where: before smoothing or after, just before sending to LED?

Yes, if the total sum of the R, B and G values is less than 30 (a value to be tweaked later), the LEDs should be off. I think I would like to try it before smoothing and see how it goes?

awawa-dev commented 3 months ago

I think I would like to try it before smoothing and see how it goes?

then you should check and modify _ledBuffer (array of colors) here https://github.com/awawa-dev/HyperHDR/blob/aa2007952bbce996ac2b2afaadfe527c558f93f2/sources/base/HyperHdrInstance.cpp#L799

chcore commented 3 months ago

I ended up solving this problem by modifying ColorSpaceCalibration::applyBacklight to simply set RGB values to zero, and then setting the Backlight threshold to a reasonably low number in the web UI. This means dark-ish areas don't light up the LEDs at all, but for me that is a much better experience than showing the incorrect color. I would even suggest that this functionality to be officially added to the web UI.

I should mention that in my case, the "incorrect color in dark scenes" problem stems from my manual color calibration settings. If I reset them all to default, the above hack is not needed, but at the cost of mostly inaccurate colors across the board.

LMaier-dev commented 3 months ago

I ended up solving this problem by modifying ColorSpaceCalibration::applyBacklight to simply set RGB values to zero, and then setting the Backlight threshold to a reasonably low number in the web UI. This means dark-ish areas don't light up the LEDs at all, but for me that is a much better experience than showing the incorrect color. I would even suggest that this functionality to be officially added to the web UI.

Adding this to the UI would be amazing and exactly what I had in mind with this issue

I should mention that in my case, the "incorrect color in dark scenes" problem stems from my manual color calibration settings. If I reset them all to default, the above hack is not needed, but at the cost of mostly inaccurate colors across the board.

yeah same