-
-
Notifications
You must be signed in to change notification settings - Fork 7
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
[Feature] Customize error function in ColorDistanceSensor.color() #627
Comments
Actually, not really: Fun fact, it sounds like we are almost doing exactly the same. Our current cost function is:
So maybe these weights should be configurable. It would be great if you want to have a look through the referenced code to see if you can find any mistakes. I'm also open to changing the default weights if we find that yours are better across a range of applications.
The original data is RGB so this is possible. In general we seem to be getting better results with HSV though. |
I was aware that the cost function looks similar, but I assume that implementing it in C is more efficient than running it in micropython. I had referenced the source code as well when working on this, but was surprised just now to see that it seems to use a large weight for saturation. After looking into it, I might have referenced the wrong version of my implementation, since in a previous version I had used this: sdelta = 2*(color.s-test_color.s)
vdelta = (color.s-test_color.s)
hdelta = 2*(((color.h-test_color.h + 180) % 360) - 180)
err = 2*sdelta*sdelta + hdelta*hdelta + vdelta*vdelta Which is equivalent to the weight 8 in saturation, 4 in hue and 1 in value. This approach should have been the one that was more reliable for me than default color matching. Since I am now using a quite different approach, as outlined in #619 (comment) I don't use an error function like this for development anymore, but since I have dumped my logged data to PC, it might be easy for me to try to get reliable weights for the error function. |
Probably the main reason for bad performance of the original function is the noise in the hue due to the low saturation of the dark gray tracks and the black floor. Here is the data for a train driving over [blue, green, red, blue] markers in HSV and RGB: So maybe the proper way to match colors would be to calculate the euclidean distance in the hsv cone: At some point I did try this by basically copying from here: https://stackoverflow.com/a/39113477 |
Is "black" or "no color" in your list of matching colors? I tried a similar train color sensor project a few months ago (I didn't use it extensively, so I don't know how reliable it was long term). I found that if I only put the colors I wanted to match in the list (using the built-in color matching) then there were errors. But if I also included "colors" I didn't want, which included the color of the track and the color of the floor underneath the track, then the matching seemed to work fairly well. |
Can you add a scale to the graphs so that we can see what the threshold is for the noise levels? |
Yes, that was one of the first realizations for me as well. For detectable colors I included the track sleepers, the floor, and each of the markers colors
Sorry about that. There are actually scales, but due to transparency they don't show up well in dark mode on github. If I click on the images, I can see the scales though. |
Sure enough - if you squint you can see them. |
Here is the data for the above plots, and the plots without transparency. #morning, lights on, other side, with reflection, fixed hue buffer
hbuf = [81, 120, 60, 75, 0, 105, 105, 111, 111, 107, 96, 72, 90, 75, 142, 90, 100, 120, 127, 127, 111, 102, 103, 85, 94, 96, 126, 60, 110, 120, 127, 97, 112, 103, 120, 101,
90, 90, 71, 132, 60, 90, 120, 120, 112, 120, 90, 108, 101, 107, 78, 90, 90, 90, 30, 112, 105, 130, 93, 114, 95, 105, 90, 90, 90, 120, 120, 130, 105, 105, 111, 100, 97, 75, 73, 67, 66, 66, 67, 68, 66, 66, 65, 67, 68, 65, 65, 67, 66, 66, 67, 70, 65, 66, 65, 67, 67, 67, 67, 69, 86, 90, 135, 50, 60, 90, 105, 120, 105, 90, 94, 90, 90,
84, 96, 37, 90, 90, 130, 130, 114, 108, 107, 111, 109, 109, 85, 126, 60, 90, 45, 120, 120, 130, 78, 109, 101, 101, 85, 75, 30, 67, 90, 100, 130, 110, 97, 110, 100, 97, 90, 103, 81, 108, 108, 105, 105, 0, 110, 85, 109, 97, 100, 72, 135, 5, 177, 179, 0, 0, 0, 0, 179, 179, 0, 0, 179, 1, 0, 178, 0, 1, 0, 0, 0, 0, 0, 179, 179, 0, 177,
177, 157, 150, 120, 120, 120, 94, 94, 105, 107, 94, 135, 100, 0, 120, 80, 112, 120, 120, 105, 103, 111, 111, 82, 127, 60, 90, 120, 142, 120, 112, 94, 107, 99, 97, 97, 90, 80, 90, 90, 105, 110, 110, 76, 112, 105, 102, 90, 90, 75, 127, 127, 130, 120, 114, 113, 108, 110, 108, 108, 108, 108, 108, 108, 110, 108, 108, 108, 108, 108, 108, 108, 108, 108, 107, 109, 110, 107, 107, 110, 110, 103, 97, 95, 96, 100, 80, 135, 60, 30, 130, 100, 120, 114, 77, 77, 97, 96, 90, 127, 60, 75, 90, 120, 120, 138, 120, 114, 90, 82, 82, 85, 105, 108, 30, 90, 90, 0, 120, 110, 120, 114, 78, 99, 103, 90, 90, 127, 60, 75, 90, 90, 90, 114, 108, 116, 100, 99, 72, 90, 110, 120, 0, 60, 120, 135, 120, 120, 120, 120, 81, 103, 94, 60, 60, 50, 0, 0, 60, 120, 75, 105, 110, 120, 111, 90, 90, 105, 124, 90, 90, 138, 120, 110, 110, 116, 100, 60, 117, 120, 90, 90, 135, 120, 112, 111, 107, 78, 115, 90, 60, 90, 120, 105, 110, 127, 117, 100, 63, 116, 100, 0, 90, 120, 130, 120, 113, 115, 103, 85, 115, 96, 60, 90, 90, 36, 60, 120, 130, 120, 120, 120, 110, 120, 114, 75, 116, 111, 51, 123, 69, 0, 30, 90, 120, 120, 120, 105, 105, 109, 81, 107, 100, 102, 116, 116, 131, 75, 30, 138, 105, 90, 120,
105, 120, 90, 100, 94, 85, 96, 84, 145, 90, 0, 90, 120, 120, 110, 110, 127, 110, 105, 116, 101, 101, 85, 97, 125, 30, 90, 0, 130, 120, 135, 105, 120, 116, 97, 103, 80, 112, 90, 67, 114, 30, 67, 100, 120, 120, 105, 105, 102, 110, 110, 82, 99, 84, 82, 47, 140, 90, 0, 135, 120, 120, 120, 111, 120, 96, 80, 84, 100, 112, 0, 120, 0, 105, 90, 120, 105, 108, 101, 120, 120, 90, 90, 128, 75, 60, 120, 60, 75, 0, 120, 120, 120, 108, 90, 104, 107, 97, 110, 90, 85, 90, 100, 60, 75, 120, 120, 120, 110, 110,
107, 105, 65, 105, 90, 94, 63, 30, 120, 0, 135, 135, 105, 105, 105, 114, 104, 70, 90, 75, 80, 63, 120, 60, 97, 120, 120, 120, 108, 111, 100, 100, 90, 84, 120, 96, 120, 75, 90, 90, 135, 120, 105, 105, 103, 112, 114, 70, 108, 96, 90, 60, 30, 75, 100, 120, 120, 120, 114, 90, 107, 109, 85, 103, 90, 84, 60, 105, 90, 60, 120, 120, 120,
108, 111, 113, 107, 120, 90, 95, 75, 71, 120, 0, 100, 135, 120, 120, 105, 116, 80, 103, 94, 78, 107, 90, 90, 150, 30, 60, 90, 135, 135, 120, 110, 107, 105, 115, 99, 116, 90, 72, 130, 0, 105, 90, 120, 110, 110, 116, 107, 107, 116, 75, 120, 81, 96, 130, 30, 60, 90, 105, 105, 114, 111, 90, 103, 107, 63, 85, 99, 90, 56, 110, 90, 90, 90, 114, 130, 115, 80, 90, 107, 66, 112, 75, 109, 120, 45, 0, 0, 105, 95, 120, 111, 114, 112, 105, 60, 114, 85, 102, 150, 30, 90, 130, 100, 105, 120, 110, 115, 103, 105, 101, 125, 90, 67, 120, 60, 90, 90, 130, 120, 100, 103, 113, 90, 66, 105, 90, 100, 60, 90, 60, 60, 120, 100, 112, 120, 100, 114, 105, 75, 115, 96, 96, 150, 60, 60,
60, 100, 75, 110, 100, 117, 102, 105, 90, 90, 130, 49, 90, 26, 80, 80, 120, 110, 114, 65, 105, 102, 82, 105, 100, 78, 135, 60, 90, 120, 120, 120, 111, 84, 103, 102, 96, 113, 105, 60, 127, 120, 75, 120, 120, 112, 111, 86, 113, 120, 75, 120, 96, 101, 120, 60, 75, 110, 120, 120, 114, 111, 107, 103, 78, 95, 107, 97, 90, 60, 60, 75, 120, 110, 120, 130, 82, 110, 90, 90, 109, 78, 72, 120, 0, 0, 120, 120, 105, 108, 100, 110, 103, 103, 114, 90, 90, 35, 75, 0, 90, 165, 120, 120, 115, 75, 105, 85, 101, 103, 78, 90, 128, 75, 90, 120, 130, 116, 122, 101, 97, 95, 93, 112, 60, 60, 60, 120, 0, 110, 120, 116, 116, 113, 109, 112, 109, 110, 110, 110, 110, 109, 110, 110, 109, 110, 110, 110, 111, 109, 110, 111, 111, 109, 109, 112, 110, 110, 111, 110, 107, 93, 81, 105, 60, 90, 100, 112, 105, 100, 107, 95, 108, 94, 85, 90, 90, 60, 90, 0, 120, 105, 108, 101, 114, 97, 120, 90, 96, 85, 105, 105, 100, 110, 112, 110, 90, 110, 99, 107, 84, 100, 82, 120, 60, 60, 120, 90, 97, 114, 104, 101, 101, 103, 90, 45, 75, 90, 0, 120, 120, 94, 105, 103, 107, 86, 90]
hbuf = [2*h for h in hbuf]
sbuf = [37, 29, 24, 29, 0, 29, 27, 57, 57, 36, 34, 26, 24, 24, 43, 15, 43, 43, 51, 43, 52, 27, 32, 29, 36, 29, 31, 24, 40, 32, 55, 51, 43, 60, 36, 48, 22, 22, 40, 36, 13, 29, 43, 27, 45, 37, 36, 43, 37, 32, 24, 31, 31, 15, 15, 48, 48, 57, 61, 42, 31, 43, 37, 20, 24, 31, 31, 43, 27, 55, 52, 31, 43, 57, 77, 80, 89, 88, 87, 91, 94, 94, 92,
89, 89, 91, 89, 87, 91, 90, 89, 90, 92, 88, 89, 94, 94, 88, 87, 68, 39, 36, 15, 36, 15, 29, 29, 36, 40, 49, 39, 39, 24, 31, 29, 43, 15, 32, 43, 43, 49, 39, 36, 46, 36, 36, 39, 36, 15, 17, 32, 15, 36, 27, 49, 48, 37, 34, 26, 32, 36, 45, 17, 40, 43, 52, 53, 40, 43, 36, 31, 32, 37, 32, 32, 29, 29, 0, 52, 32, 49, 39, 37, 29, 22, 62, 88, 94, 97, 97, 97, 97, 96, 98, 96, 96, 98, 97, 96, 97, 97, 96, 95, 95, 95, 95, 96, 96, 97, 95, 96, 89, 51, 15, 15, 32, 43, 43, 43, 29, 32, 39, 13, 32, 0, 32, 43, 45,
43, 52, 40, 42, 36, 36, 26, 34, 36, 32, 32, 51, 36, 36, 43, 59, 34, 43, 20, 26, 32, 29, 32, 29, 40, 52, 51, 45, 36, 42, 36, 22, 31, 26, 26, 43, 37, 82, 93, 95, 96, 95, 93, 94, 96, 93, 93, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 94, 93, 96, 96, 95, 95, 95, 57, 40, 31, 26, 32, 36, 17, 24, 15, 43, 43, 36, 43, 37, 37, 37, 29, 26, 26,
36, 29, 32, 43, 43, 61, 43, 43, 31, 19, 19, 36, 24, 46, 13, 17, 32, 0, 32, 40, 43, 43, 48, 36, 27, 22, 17, 31, 24, 29, 17, 32, 43, 52, 46, 51, 15, 36, 45, 36, 37, 20, 0, 15, 15, 32, 32, 43, 36, 37, 45, 37, 39, 20, 20, 51, 0, 13, 17, 32, 32, 51, 37, 48, 37, 37, 11, 36, 51, 15, 32, 69, 32, 40, 52, 40, 46, 29, 40, 26, 32, 32, 32, 43, 43, 52, 43, 46, 26, 37, 24, 17, 32, 29, 37, 61, 43, 31, 37, 36, 29, 0, 32, 32, 43, 13, 64, 49, 37, 24, 49, 26, 36, 13, 46, 31, 24, 13, 43, 32, 32, 43, 40, 36, 43, 40, 37, 37, 37, 34, 55, 0, 13, 29, 32, 32, 43, 48, 40, 61, 45, 46, 46, 27, 29, 29, 55, 24, 15, 65, 29, 43, 51, 48, 40, 40, 46, 40, 32, 29, 31, 39, 24, 13, 29, 43, 43, 40, 40, 43, 52, 55, 39, 39, 39, 32, 22, 40, 13, 29, 0, 43, 32, 27, 27, 29, 51, 22, 37, 13, 36, 27, 48, 36, 11, 45, 40, 32, 32, 29, 48, 49, 46, 46, 57, 27, 27, 26, 49,
32, 13, 0, 32, 43, 43, 27, 65, 43, 29, 32, 27, 49, 22, 5, 20, 0, 51, 17, 43, 59, 55, 75, 43, 43, 43, 22, 48, 32, 40, 39, 36, 32, 0, 32, 32, 43, 55, 26, 52, 32, 19, 29, 29, 36, 13, 32, 36, 29, 32, 51, 43, 40, 40, 36, 29, 29, 9, 37, 39, 48, 11, 15, 0, 32, 32, 29, 27, 27, 46, 55, 48, 19, 31, 36, 51, 37, 13, 51, 32, 43, 55, 46, 52, 46, 46, 22, 26, 40, 31, 20, 24, 15, 17, 32, 32, 51, 51, 49, 52, 26, 29, 22, 29, 19, 37, 24, 29, 43, 32, 32, 51, 43, 36, 43, 39, 37, 31, 32, 29, 26, 20, 36, 15, 32, 32,
36, 43, 49, 43, 36, 39, 22, 31, 22, 49, 46, 0, 43, 32, 32, 32, 40, 56, 36, 37, 39, 20, 32, 22, 20, 20, 24, 17, 17, 32, 32, 46, 48, 36, 40, 32, 37, 36, 24, 31, 37, 13, 29, 32, 43, 40, 57, 52, 48, 43, 37, 19, 31, 37, 29, 43, 24, 15, 32, 29, 29, 52, 57, 13, 37, 32, 36, 27, 36, 39, 40, 29, 24, 29, 29, 61, 36, 48, 36, 37, 32, 39, 36, 22, 46, 13, 22, 0, 0, 51, 70, 40, 51, 45, 39, 40, 24, 42, 31, 31, 13, 24, 15, 43, 40, 64, 46, 46, 32, 37, 32, 40, 27, 22, 26, 37, 13, 32, 32, 43, 36, 52, 49, 43, 37, 24, 26, 22, 17, 20, 36, 15, 15, 32, 40, 45, 37, 43, 46, 39, 19, 27, 29, 29, 15, 24, 15, 15, 43, 45, 52, 45, 43, 26, 32, 24, 24, 19, 49, 24, 27, 43, 43, 13, 36, 43, 37, 51, 49, 17, 37, 36, 32, 42, 24, 17, 32, 43, 36, 57, 36, 39, 49, 27, 42, 24, 26, 37, 13, 29, 32, 32, 45, 57, 53, 43, 32, 19, 31, 29, 43, 7, 24, 29, 46, 32, 32, 49, 52, 43, 42, 46, 26, 36, 26, 7, 24, 15, 32, 32, 64, 32, 66, 26, 46, 32, 27, 39, 27, 36, 52, 0, 0, 32, 32, 48, 46, 46, 32, 37, 37, 22, 17, 26, 37, 24, 13, 17, 51, 32, 32, 48, 37, 40, 31, 37, 42, 40, 20, 48, 64, 32, 32, 43, 52, 52, 39, 43, 27, 49, 22, 13, 24, 15, 32, 0, 40, 32, 52, 52, 85, 91, 95, 95, 94, 94, 96, 93, 94, 95, 96, 95, 94, 96, 96, 95, 95, 94, 94, 95, 95, 94, 94, 95, 93, 93, 94, 89, 42, 37, 11, 24, 32, 43, 55, 27, 32, 52, 31, 43, 32, 31, 24, 24, 24, 29, 0, 32, 27, 46, 56, 24, 43, 36, 43, 29, 36, 26, 26, 43, 40, 45, 52, 29, 52, 32, 40, 24, 32, 24, 34, 24, 24, 15, 43, 56, 42, 48, 36, 37, 31, 40, 11, 24, 15, 0, 32, 32, 43, 43, 40, 31, 40, 40]
vbuf = [24, 17, 9, 7, 5, 7, 9, 13, 13, 24, 19, 24, 20, 20, 11, 7, 7, 7, 9, 11, 15, 24, 26, 26, 24, 22, 20, 9, 9, 7, 7, 9, 11, 17, 27, 26, 27, 27, 24, 17, 9, 7, 7, 9, 9, 13,
17, 27, 26, 26, 26, 24, 24, 7, 7, 9, 9, 11, 19, 29, 24, 22, 20, 24, 20, 17, 17, 7, 9, 13, 15, 24, 24, 27, 29, 45, 42, 52, 49, 45, 48, 48, 49, 52, 48, 46, 52, 49, 46,
51, 52, 45, 45, 51, 52, 43, 43, 42, 43, 29, 24, 20, 17, 9, 7, 7, 7, 9, 11, 17, 22, 19, 20, 20, 22, 11, 7, 7, 7, 7, 11, 15, 24, 26, 27, 27, 22, 17, 7, 7, 7, 7, 9, 13,
19, 26, 26, 29, 29, 24, 9, 9, 7, 9, 7, 13, 17, 27, 26, 27, 24, 26, 24, 19, 19, 7, 7, 9, 13, 24, 26, 24, 20, 22, 22, 32, 48, 64, 73, 73, 73, 73, 78, 75, 78, 79, 75, 77, 77, 79, 75, 77, 79, 79, 79, 79, 78, 79, 72, 64, 40, 20, 9, 7, 7, 11, 13, 19, 19, 26, 26, 22, 19, 11, 7, 7, 7, 9, 11, 15, 24, 26, 24, 24, 20, 15, 9, 7, 7, 9, 9, 13,
20, 26, 26, 24, 24, 20, 11, 7, 7, 7, 9, 13, 20, 29, 27, 29, 27, 27, 24, 19, 19, 7, 9, 17, 31, 49, 61, 64, 65, 67, 62, 64, 64, 65, 61, 61, 61, 61, 61, 61, 61, 61, 59,
64, 66, 62, 60, 64, 62, 62, 31, 26, 24, 24, 24, 20, 15, 9, 7, 7, 7, 9, 13, 24, 24, 26, 22, 19, 19, 9, 7, 7, 7, 7, 9, 11, 13, 20, 26, 26, 24, 20, 13, 9, 7, 7, 5, 7, 9, 11, 13, 20, 24, 31, 24, 22, 17, 9, 7, 7, 7, 7, 11, 13, 17, 24, 24, 26, 24, 20, 11, 9, 7, 7, 7, 7, 7, 9, 13, 19, 24, 22, 29, 29, 20, 9, 9, 7, 7, 7, 9, 9, 15, 24, 24,
20, 20, 17, 7, 7, 7, 7, 9, 13, 24, 24, 26, 26, 9, 7, 7, 7, 7, 11, 15, 24, 26, 29, 24, 9, 7, 7, 7, 9, 15, 24, 24, 26, 27, 13, 7, 7, 7, 7, 9, 15, 26, 24, 29, 26, 24, 27, 27, 24, 20, 9, 9, 7, 7, 7, 7, 9, 9, 13, 19, 24, 24, 32, 29, 20, 9, 9, 7, 7, 7, 7, 9, 11, 15, 19, 24, 24, 22, 29, 29, 17, 9, 7, 7, 7, 7, 9, 9, 11, 19, 24, 24, 24, 22, 20, 19, 9, 9, 7, 7, 7, 9, 9, 11, 13, 17, 24, 26, 26, 24, 22, 19, 9, 7, 7, 7, 7, 9, 9, 13, 17, 22, 24, 27, 27, 24, 20, 17, 9, 9, 9, 7, 7, 7, 9, 11, 15, 15, 24, 31, 24, 20, 22, 11, 9, 7, 7, 7, 7, 9, 11, 13, 22, 24, 24, 22, 22, 20, 11, 9, 9, 7, 7, 7, 9, 11, 13, 13, 24, 27, 27, 24, 20, 15, 9, 7, 5, 7, 7, 7, 9, 20, 24, 26, 27, 26, 22, 20, 19, 11, 9, 7, 7, 9, 7, 9, 9, 24, 26, 26, 27, 24, 22, 20, 9, 7, 7, 7, 7, 7, 9, 9, 26, 24, 26, 26, 24, 20, 20, 13, 9, 9, 7, 7, 7, 13, 15, 24, 24, 22, 24, 24, 20,
19, 9, 7, 7, 7, 7, 9, 9, 17, 24, 24, 26, 27, 22, 20, 20, 9, 7, 7, 7, 7, 9, 13, 17, 24, 24, 24, 29, 24, 22, 20, 11, 9, 7, 7, 7, 9, 13, 17, 24, 24, 26, 27, 24, 24, 19,
15, 9, 7, 7, 7, 7, 11, 17, 20, 24, 22, 29, 26, 22, 19, 19, 9, 7, 7, 7, 7, 13, 15, 24, 24, 22, 24, 27, 20, 20, 20, 9, 7, 7, 7, 9, 11, 15, 22, 24, 26, 27, 29, 24, 22, 17, 9, 7, 7, 7, 7, 11, 13, 20, 24, 26, 27, 27, 24, 22, 20, 13, 9, 7, 7, 9, 9, 15, 20, 24, 26, 27, 27, 24, 20, 20, 11, 7, 7, 9, 9, 11, 17, 26, 26, 24, 31, 29, 24, 20, 19, 9, 7, 7, 9, 9, 13, 15, 24, 24, 24, 24, 27, 22, 20, 13, 9, 7, 7, 7, 9, 13, 17, 24, 24, 26, 29, 22, 22, 19, 9, 7, 7, 7, 9, 9, 13, 17, 26, 24, 27, 27, 22, 22, 17, 9,
7, 7, 7, 9, 13, 17, 24, 24, 24, 26, 20, 20, 19, 9, 9, 7, 7, 9, 9, 13, 20, 24, 24, 29, 26, 20, 19, 17, 9, 7, 7, 7, 9, 13, 17, 22, 24, 22, 26, 20, 20, 13, 9, 7, 7, 7, 9, 13, 17, 24, 26, 27, 27, 22, 22, 17, 9, 7, 7, 7, 7, 11, 15, 24, 26, 26, 29, 24, 20, 17, 9, 7, 7, 7, 9, 11, 15, 20, 24, 24, 27, 26, 24, 17, 15, 7, 7, 7, 7, 9, 13, 15, 22, 24, 24, 27, 24, 20, 20, 9, 9, 7, 9, 7, 7, 15, 20, 24, 24, 26, 26, 24, 19, 17, 9, 7, 7, 7, 15, 26, 26, 24, 27, 24, 22, 20, 9, 7, 7, 7, 9, 11, 15, 15, 36, 57, 65,
65, 67, 67, 66, 66, 67, 67, 66, 67, 69, 67, 67, 68, 66, 68, 70, 66, 68, 70, 70, 67, 69, 70, 62, 55, 26, 24, 20, 9, 7, 7, 7, 9, 11, 15, 24, 27, 26, 24, 26, 26, 9, 7, 5, 7, 9, 13, 17, 26, 24, 24, 19, 22, 20, 19, 19, 7, 9, 9, 13, 17, 26, 26, 26, 26, 24, 20, 19, 9, 9, 7, 11, 17, 29, 27, 27, 26, 29, 24, 22, 9, 7, 7, 7, 7, 19, 27, 26, 27, 24, 24]
rbuf = [13, 9, 6, 5, 4, 4, 5, 7, 7, 13, 10, 13, 12, 12, 6, 5, 4, 4, 4, 6, 7, 13, 15, 14, 14, 12, 10, 6, 5, 4, 4, 5, 6, 8, 14, 14, 16, 16, 13, 9, 5, 5, 4, 5, 5, 7, 10, 14, 14, 15, 15, 14, 14, 5, 5, 5, 5, 6, 9, 15, 14, 12, 11, 14, 12, 8, 8, 4, 5, 6, 8, 14, 13, 14, 13, 19, 16, 21, 20, 17, 16, 16, 18, 21, 19, 17, 20, 20, 17, 20, 21, 18, 16,
20, 20, 15, 15, 16, 17, 14, 14, 12, 10, 6, 5, 5, 4, 5, 6, 9, 12, 11, 12, 11, 12, 6, 5, 4, 4, 4, 6, 8, 13, 13, 15, 15, 12, 9, 5, 4, 4, 5, 5, 7, 10, 14, 14, 16, 16, 13, 6, 5, 4, 5, 4, 7, 9, 14, 14, 15, 14, 15, 13, 10, 10, 4, 4, 6, 6, 13, 13, 13, 11, 12, 13, 15, 18, 22, 23, 23, 23, 23, 27, 24, 28, 28, 24, 26, 27, 27, 23, 27, 28, 28,
28, 28, 27, 28, 24, 21, 12, 7, 5, 5, 5, 6, 7, 10, 10, 14, 14, 12, 11, 6, 5, 4, 4, 5, 6, 7, 13, 14, 13, 13, 11, 8, 5, 4, 4, 5, 5, 8, 11, 13, 14, 13, 14, 11, 6, 5, 4, 4, 5, 7, 11, 15, 15, 15, 15, 16, 14, 10, 10, 4, 5, 7, 10, 18, 23, 25, 27, 28, 24, 27, 27, 25, 24, 24, 24, 24, 24, 24, 24, 24, 22, 26, 27, 23, 23, 26, 24, 24, 16, 15, 13, 14, 13, 12, 8, 6, 5, 4, 4, 5, 7, 12, 12, 15, 12, 11, 10, 5, 4, 4, 4, 4, 4, 5, 7, 11, 15, 15, 13, 12, 6, 5, 4, 4, 4, 4, 5, 5, 7, 10, 13, 17, 13, 13, 9, 6, 4, 4, 4,
4, 5, 6, 8, 14, 13, 14, 14, 10, 7, 5, 5, 5, 4, 4, 4, 5, 7, 10, 12, 12, 17, 17, 11, 5, 5, 4, 4, 4, 4, 5, 7, 12, 13, 12, 11, 8, 5, 4, 4, 4, 5, 7, 12, 12, 14, 14, 5, 4,
4, 4, 4, 6, 8, 13, 13, 16, 13, 6, 4, 4, 4, 5, 7, 12, 14, 14, 15, 7, 5, 4, 4, 4, 5, 7, 13, 12, 17, 13, 13, 14, 17, 13, 11, 6, 5, 4, 4, 4, 4, 5, 5, 7, 10, 12, 12, 17, 16, 10, 6, 5, 5, 4, 4, 4, 5, 6, 7, 10, 12, 12, 13, 16, 16, 8, 6, 5, 4, 4, 4, 4, 5, 6, 10, 12, 13, 13, 12, 11, 10, 6, 5, 5, 4, 4, 5, 5, 6, 7, 8, 13, 14, 14, 13, 12, 9,
5, 5, 4, 4, 4, 5, 5, 7, 8, 13, 13, 16, 15, 13, 10, 9, 6, 5, 5, 4, 4, 4, 5, 6, 8, 8, 12, 17, 13, 11, 11, 6, 5, 4, 4, 4, 4, 5, 5, 7, 12, 13, 13, 11, 12, 12, 7, 5, 4, 4, 4, 4, 5, 5, 7, 7, 14, 16, 14, 13, 11, 8, 5, 4, 4, 4, 4, 4, 5, 11, 13, 14, 16, 14, 12, 12, 11, 6, 5, 4, 4, 4, 4, 5, 5, 13, 14, 14, 16, 13, 12, 10, 6, 5, 4, 4, 4, 4, 5, 5, 13, 12, 14, 16, 13, 12, 10, 7, 5, 5, 4, 4, 4, 6, 8, 12, 12, 13, 14, 12, 11, 10, 6, 5, 4, 4, 4, 4, 4, 9, 12, 14, 14, 15, 12, 12, 10, 6, 5, 4, 4, 4, 4, 7, 10, 13,
13, 13, 16, 13, 12, 11, 7, 6, 5, 4, 4, 5, 7, 8, 13, 13, 13, 16, 13, 13, 9, 8, 5, 4, 4, 4, 4, 6, 7, 12, 13, 12, 17, 15, 13, 11, 11, 6, 4, 4, 4, 4, 6, 7, 13, 13, 12, 13, 15, 12, 11, 11, 5, 4, 4, 4, 5, 6, 7, 11, 13, 14, 16, 15, 13, 12, 9, 6, 5, 4, 4, 4, 5, 7, 12, 12, 14, 15, 16, 13, 12, 11, 7, 6, 5, 5, 4, 5, 7, 12, 13, 15, 15, 15, 13, 10, 11, 6, 5, 5, 5, 4, 6, 8, 13, 13, 13, 17, 15, 13, 11, 11, 6, 5, 4, 5, 5, 6, 8, 13, 13, 13, 13, 15, 13, 11, 7, 5, 4, 4, 4, 5, 7, 9, 12, 13, 15, 16, 13, 13, 10, 6, 5, 5, 4, 5, 5, 7, 9, 13, 13, 16, 15, 12, 12, 10, 6, 5, 5, 4, 5, 7, 9, 12, 14, 13, 16, 12, 12, 10, 6, 5, 4, 4, 5, 5, 7, 10, 12, 12, 17, 14, 12, 10, 9, 6, 4, 4, 4, 5,
7, 10, 12, 12, 13, 13, 12, 11, 7, 5, 4, 4, 4, 5, 7, 9, 13, 14, 16, 15, 12, 11, 10, 6, 4, 4, 4, 4, 6, 8, 13, 14, 14, 17, 13, 11, 10, 6, 5, 4, 4, 5, 6, 7, 11, 12, 13, 16, 13, 13, 9, 7, 5, 4, 4, 4, 5, 6, 8, 12, 12, 12, 16, 13, 11, 11, 6, 5, 4, 4, 4, 4, 7, 11, 13, 13, 15, 14, 13, 11, 9, 5, 4, 4, 4, 7, 13, 14, 13, 16, 13, 12, 11, 6, 5, 4, 4, 5, 6, 7, 7, 14, 23, 25, 25, 27, 27, 25, 27, 27, 26, 25, 27, 28, 25, 25, 27, 26, 28, 28, 26, 27, 29, 28, 26, 29, 29, 25, 24, 14, 13, 12, 6, 4, 4, 4, 5, 6, 8, 13, 14, 14, 13, 15, 15, 6, 5, 4, 4, 5, 6, 8, 15, 13, 13, 10, 12, 12, 11, 11, 4, 5, 5, 7, 10, 13, 15, 14, 14, 13, 12, 10, 6, 6, 5, 6, 8, 15, 14, 15, 15, 16, 13, 13, 6, 5, 4, 4, 4, 10, 15, 14, 15, 13, 13]
dump_index = 400
true_colors = ['blue', 'green', 'red', 'blue'] |
For completeness, that's the code for getting to the hsv plot: from matplotlib import pyplot as plt
lineweight = .4
import numpy as np
hue = np.roll(np.array(hbuf), -dump_index)
sat = np.roll(np.array(sbuf), -dump_index)
val = np.roll(np.array(vbuf), -dump_index)
ref = np.roll(np.array(rbuf), -dump_index)
hue = (hue-20)%360
lineweight = .4
fig = plt.figure(dpi=150,)
fig.patch.set_facecolor('white')
plt.plot(sat, lw=lineweight, label="saturation")
plt.plot(val, lw=lineweight, label="value")
#plt.plot(hue, lw=lineweight, label="hue", ls="", marker="x", markersize=.4)
plt.plot(hue, lw=lineweight, label="hue")
plt.plot(ref, lw=lineweight, label="reflection")
plt.legend()
plt.show() |
After just a quick glance at the code, it looks like we might need to increase our thresholds for low value and low saturation quite a bit. We may also need to make these dependent on the sensor type. I also wonder if it would be possible to do some sort of discrete time analysis of the hue and saturation to detect if these signal are currently "noisy" or not instead of the current method of "if X is below threshold then Y is noisy". |
Did you use the standard colors like |
This is probably where the documentation should be clearer. The intention is indeed to include all colors that it can detect in your application. Maybe |
I used my own, measured using |
But back then I didn't know that the hue was so erratic, I probably could have improved the scheme a lot if I put in colors for the floor and sleepers with the maximum range of hues. But to reiterate, I think doing the color error like outlined here seems like the most sensible thing to me, as it doesn't care for the undefined hue for dark or unsaturated colors. |
That sounds good. Are you interested in giving it a try with a pull request? (And since this happens under the hood, there’s no rush.) |
Sure, I'll try! Never compiled the firmware myself, but I had been meaning to try anyways. |
I have now managed to set the environment up (using windows subsystem for linux) and can compile the firmware, so I will work on a pull request for this. Since the mapping requires trigonometric functions, is there a implementation for fixed point sine/cosine in the codebase that I can use? I am guessing that we want to avoid floating point functions because Move Hub doesn't have floats. |
We are using https://github.com/PetteriAimonen/libfixmath already. |
Implement the color error by calculating the cartesian distance between the colors in the HSV cone. This should be more insensitive to fluctuating hue values on dark and unsaturated colors. This has been discussed further in pybricks/support#627
Implement the color error by calculating the cartesian distance between the colors in the HSV cone. This should be more insensitive to fluctuating hue values on dark and unsaturated colors. This has been discussed further in pybricks/support#627
Implement the color error by calculating the cartesian distance between the colors in the HSV cone. This should be more insensitive to fluctuating hue values on dark and unsaturated colors. This has been discussed further in pybricks/support#627
Implement the color error by calculating the cartesian distance between the colors in the HSV cone. This should be more insensitive to fluctuating hue values on dark and unsaturated colors. This has been discussed further in pybricks/support#627
Implement the color error by calculating the cartesian distance between the colors in the HSV cone. This should be more insensitive to fluctuating hue values on dark and unsaturated colors. This has been discussed further in pybricks/support#627
Is your feature request related to a problem? Please describe.
In my project I want to detect 2x8+ color plates on train tracks on a train with a Color & Distance sensor pointed down at the tracks. The reliability of detecting them correctly is very important. In the past, I've tried to use
ColorDistanceSensor.color()
along with customdetectable colors
for this, but I found that using my own detection algorithm using the following error function worked much more reliably (edit: see below comment for correction):Notice that I doubled the weight for the saturation delta compared to the hue and value.
Describe the solution you'd like
The above solution probably slower and more memory-intensive than just using the builtin color matching, so I propose that we could introduce a custom weighting for hue, saturation and value in
ColorDistanceSensor.color()
to make it more flexible for such usecases. We could also choose between squared sum of the errors or just the sum of absolutes (or more?).My proposed API for this would change the parameters of
ColorDistanceSensor.detectable_colors(colors)
to:ColorDistanceSensor.detectable_colors(colors, hsv_weights, method)
where
hsv_weights
might be a tuple of weights andmethod
could be either"squared"
,"linear"
(or an arbitrary integer exponent > 0).Another method could be to perform the delta in RGB space (though I realize converting to rgb is not trivial depending on the resources we want to spend on this).
Another possibility could be to provide a custom micropython callable for the error function, but then the advantage over matching the color fully in micropython might diminish.
Describe alternatives you've considered
One could implement the matching in micropython as above, which costs performance and memory.
Additional context
This issue is inspired by the discussion in #619 (comment)
The text was updated successfully, but these errors were encountered: