Is Delta E a reliable guide to the difference between colors? - colors

I'm attempting to order some color swatches by "maximum difference" and am getting some odd results. For example, in the image below, colors numbers 5 and 14 appear, at least to my (non-colorblind) eye, rather similar, much more so than some of the following colors, but yet seem to have a higher minimum ΔE (when calculated against all the previous colors) than many of those colors that follow it.
Is ΔE considered a reliable way of calculating a "perceptual distance" between colors, or should I be using something else?
In order, the colors shown here are:
> x.hex
[1] "#060186" "#8EF905" "#F5C5F7" "#805200" "#0DE0FE" "#D0135D" "#0B834F" "#FABF74" "#417BEA" "#FA4D01"
[11] "#DC39FC" "#590708" "#919913" "#01DDAE" "#068896" "#D28B8B" "#7C4C8E" "#A3BCE7" "#0C5378" "#F1E11E"
[21] "#A24731" "#495C0D" "#01B633" "#4A30FE" "#BB7D0A" "#680F41" "#C1D597" "#FC75C1" "#A786C7" "#29A4DD"
[31] "#FD0A3D" "#43A99B" "#B16A8D" "#D002A2" "#BA7755" "#FECBB6" "#253467" "#FF9143" "#8A763A" "#5960A6"
[41] "#B79D66" "#70A271"
And the minimum ΔE against the previous colors:
> DeList
[1] 117.25473 69.53788 55.00019 46.90173 38.54371 37.20359 36.32807 35.23608 28.57360 27.10889
[11] 26.77178 25.24130 24.39958 24.24133 22.51525 22.23315 20.50791 19.93881 19.63842 19.45253
[21] 19.31200 19.04087 18.90102 18.64973 18.25806 18.08846 17.55115 17.19687 16.82420 15.35578
[31] 15.17018 14.95605 14.77414 14.67706 14.67703 14.37527 14.16665 14.02716 14.00375 13.90574
[41] 13.84133
I'm calculating ΔE using the R package spacesXYZ, using the formula:
spacesXYZ::DeltaE( lab.matrix[i,], lab.matrix[j,], 2000 )
and calculating the hex code from the LAB matrix using:
x <- lab.matrix[pal.list,] # extract the LAB numbers from the matrix
x.lab <- colorspace::LAB(x) # convert to an LAB colorspace class
(x.hex <- colorspace::hex(x.lab)) # convert to hex string

Related

Plotting a column of precision floating point values

I have a sequence of data that I have modified to the following:
load 'tables/csv'
load 'graphics/plot'
x =: readcsv 'table_ctl.csv'
dat =: 4 {::|:x
dat
The data in question is pulling the fourth column, that has been transposed of the following sequence of the array. Below is a sample of the first five values for the column.
13.5598 13.6815 14.027 14.132 14.0104
However upon running:
plot dat
I get the following error:
|option not found: 13.5598: signal
| signal'option not found: ',j
Is this error due to the precision of the floating point values?
Thank you.
You're getting this error as you're passing a list of boxes to plot, and plot is expecting some of these boxes to contain the data to plot, and some other boxes to contain control data. 13.5598 is not a valid option for a plot.
fread 'table_ctl.csv'
a,b,0,1,13.5598
a,b,0,1,13.6815
a,b,0,1,14.027
a,b,0,1,14.132
a,b,0,1,14.0104
4 {::|: readcsv 'table_ctl.csv'
┌───────┬───────┬──────┬──────┬───────┐
│13.5598│13.6815│14.027│14.132│14.0104│
└───────┴───────┴──────┴──────┴───────┘
Probably you were thinking that {:: automatically unboxes, but it only does this if the path you give it designates a single box. See the top text at Fetch. The other problem to have is that the contents of these boxes are strings, not floats:
$ > 4 {::|: readcsv 'table_ctl.csv'
5 7
|."1 > 4 {::|: readcsv 'table_ctl.csv'
8955.31
5186.31
720.41
231.41
4010.41
So, to plot your numbers: plot > makenum 4 {::|: readcsv 'table_ctl.csv' which starts with the list of boxes, then turns each box into a box of a float, then unboxes the list and plots it. makenum comes with readcsv and is like a smart ". each in this case, as it would leave non-numeric boxes alone.
There's a bit more to set up, but jd might also work for this:
fread 'table_ctl.cdefs'
1 label byte 1
2 name varbyte
3 enabled boolean
4 weight int
5 score float
options , LF NO \ 0 iso8601-char
load 'data/jd'
!!! Jd key: non-commercial use only!
jdwelcome_jd_ NB. run this sentence for important information
jdadminnew'temp'
CSVFOLDER=:'/path/to/csv/directory'
jd'csvrd table_ctl.csv data'
jd'info schema'
┌─────┬───────┬───────┬─────┐
│table│column │type │shape│
├─────┼───────┼───────┼─────┤
│data │label │byte │1 │
│data │name │varbyte│_ │
│data │enabled│boolean│_ │
│data │weight │int │_ │
│data │score │float │_ │
└─────┴───────┴───────┴─────┘
jd'get data score'
13.5598 13.6815 14.027 14.132 14.0104

Deriving boolean expressions from hand drawn logic gate diagrams with python OpenCv

Using tensorflow I identified all the gates, letters and nodes.
When identifying all above components, it draws a rectangle box around each component.
Therefore, in the following array it contains list of all the components detected. Each list is in the following order.
Name of component
X, Y coordinates of top left corner of rectangle
X, Y coordinates of right bottom of rectangle
Nodes (Black Points) are used to indicate a bridge over a line without crossing.
Array of all above components.
labels =[['NODE',(1002.9702758789062, 896.4686675071716), (1220.212585389614, 1067.1142654418945)], ['NODE',(1032.444071739912, 635.7160077095032),(1211.6839590370655, 763.4382424354553)],['M', (57.093908578157425,607.6229677200317),(311.9765570014715,833.807623386383)],['NODE', (344.5295810997486, 806.3690414428711), (501.8982524871826, 930.6454839706421)], ['Z', (21.986433800309896, 1327.9791088104248), (266.36098374426365, 1565.158670425415)], ['OR', (476.0066536962986, 574.401759147644), (918.3125713765621, 1177.1423168182373)], ['NODE', (333.50814148783684, 1058.0092916488647), (497.6142471432686, 1202.9034795761108)], ['K', (37.06201596558094, 870.0414619445801), (311.77860628068447, 1105.8665227890015)], ['AND', (665.9987451732159, 1227.940999031067), (1062.7052736580372, 1594.6843948364258)],['AND', (1373.9987451732159, 204.940999031067), (1703.7052736580372, 612.6843948364258)], ['NOT', (694.2882044911385, 260.5083291530609), (1027.812717139721, 450.35294365882874)], ['XOR', (2027.6711627840996, 593.0362477302551), (2457.9011510014534, 1093.9836854934692)], ['J', (85.69029207900167, 253.8458535671234), (334.48535946011543, 456.5887498855591)], ['OUTPUT', (2657.3825285434723, 670.8418045043945), (2929.8974316120148, 975.4852895736694)]]
Then, using line detection algorithm I identified all the 17 lines connecting each component.
All above 17 lines take as a list of arrays, and those lines are not in a correct order and each line has 2 end points.
lines = [[(60, 1502), (787, 1467)], [(125, 1031), (691, 988)], [(128, 772), (685, 758)], [(131, 336),(709,347)], [(927,350),(1455, 348)], [(400, 1361), (792, 1369)], [(834, 843), (2343, 939)], [(915, 1430), (1119, 1424)], [(1125, 468), (1453, 470)], [(1587, 399), (1911, 405)], [(1884, 755), (2245, 814)],[(2372, 831), (2918, 859)], [(1891, 397), (1901, 767)], [(1138, 457), (1128, 738)], [(441, 738), (421, 903)], [(1125, 946), (1101, 1437)], [(420, 1098), (408, 1373)]]
When connecting those lines, it is must to consider following scenario.
It means nodes are used to indicate a bridge without crossing lines.
M is an input to the AND gate and (M.Z) is an input to the other AND gate.
So how can I generate the following Boolean Expression using above 2 arrays and above scenario? This should be a function that works for all logic gates.
It can be assumed that image is always going to read from left to right.

what type of array is being returned by tiff.imread()?

I am trying to get the RGB value of pixels from the TIFF image. So, what I did is:
import tifffile as tiff
a = tiff.imread("a.tif")
print (a.shape) #returns (1295, 1364, 4)
print(a) #returns [[[205 269 172 264]...[230 357 304 515]][[206 270 174 270] ... [140 208 183 286]]]
But since we know pixel color ranges from (0,255) for RGB. So, I don't understand what are these array returning, as some values are bigger than 255 and why are there 4 values?
By the way array size is 1295*1364 i.e size of image.
The normal reasons for a TIFF (or any other image) to be 4-bands are that it is:
RGBA, i.e. it contains Red, Green and Blue channels plus an alpha/transparency channel, or
CMYK, i.e. it contains Cyan, Magenta, Yellow and Black channels - this is most common in the print industry where "separations" are used in 4-colour printing, see here, or
that it is multi-band imagery, such as satellite images with Red, Green, Blue and Near Infra-red bands, e.g. Landsat MSS (Multi Spectral Scanner) or somesuch.
Note that some folks use TIFF files for topographic information, bathymetric information, microscopy and other purposes.
The likely reason for the values to be greater than 256, is that it is 16-bit data. Though it could be 10-bit, 12-bit, 32-bit, floats, doubles or something else.
Without access to your image, it is not possible to say much more. With access to your image, you could use ImageMagick at the command-line to find out more:
magick identify -verbose YourImage.TIF
Sample Output
Image: YourImage.TIF
Format: TIFF (Tagged Image File Format)
Mime type: image/tiff
Class: DirectClass
Geometry: 1024x768+0+0
Units: PixelsPerInch
Colorspace: CMYK <--- check this field
Type: ColorSeparation <--- ... and this one
Endianess: LSB
Depth: 16-bit
Channel depth:
Cyan: 16-bit <--- ... and this
Magenta: 1-bit <--- ... this
Yellow: 16-bit <--- ... and this
Black: 16-bit
Channel statistics:
...
...
You can scale the values like this:
from tifffile import imread
import numpy as np
# Open image
img = imread('image.tif')
# Convert to numpy array
npimg = np.array(img,dtype=np.float)
npimg[:,:,0]/=256
npimg[:,:,1]/=256
npimg[:,:,2]/=256
npimg[:,:,3]/=65535
print(np.mean(npimg[:,:,0]))
print(np.mean(npimg[:,:,1]))
print(np.mean(npimg[:,:,2]))
print(np.mean(npimg[:,:,3]))

How to estimate camera pose according to a projective transformation matrix of two consecutive frames?

I'm working on the kitti visual odometry dataset. I use projective transformation to register two 2D consecutive frames(see projective transformation example here
). I want to know how this 3*3 projective transformation matrix is related to the ground truth poses provided by the kitti dataset.
This dataset gives the ground truth poses (trajectory) for the sequences, which is described below:
Folder 'poses':
The folder 'poses' contains the ground truth poses (trajectory) for the
first 11 sequences. This information can be used for training/tuning your
method. Each file xx.txt contains a N x 12 table, where N is the number of
frames of this sequence. Row i represents the i'th pose of the left camera
coordinate system (i.e., z pointing forwards) via a 3x4 transformation
matrix. The matrices are stored in row aligned order (the first entries
correspond to the first row), and take a point in the i'th coordinate
system and project it into the first (=0th) coordinate system. Hence, the
translational part (3x1 vector of column 4) corresponds to the pose of the
left camera coordinate system in the i'th frame with respect to the first
(=0th) frame. Your submission results must be provided using the same data
format.
Some samples of the given groud-truth poses:
1.000000e+00 9.043680e-12 2.326809e-11 5.551115e-17 9.043683e-12 1.000000e+00 2.392370e-10 3.330669e-16 2.326810e-11 2.392370e-10 9.999999e-01 -4.440892e-16
9.999978e-01 5.272628e-04 -2.066935e-03 -4.690294e-02 -5.296506e-04 9.999992e-01 -1.154865e-03 -2.839928e-02 2.066324e-03 1.155958e-03 9.999971e-01 8.586941e-01
9.999910e-01 1.048972e-03 -4.131348e-03 -9.374345e-02 -1.058514e-03 9.999968e-01 -2.308104e-03 -5.676064e-02 4.128913e-03 2.312456e-03 9.999887e-01 1.716275e+00
9.999796e-01 1.566466e-03 -6.198571e-03 -1.406429e-01 -1.587952e-03 9.999927e-01 -3.462706e-03 -8.515762e-02 6.193102e-03 3.472479e-03 9.999747e-01 2.574964e+00
9.999637e-01 2.078471e-03 -8.263498e-03 -1.874858e-01 -2.116664e-03 9.999871e-01 -4.615826e-03 -1.135202e-01 8.253797e-03 4.633149e-03 9.999551e-01 3.432648e+00
9.999433e-01 2.586172e-03 -1.033094e-02 -2.343818e-01 -2.645881e-03 9.999798e-01 -5.770163e-03 -1.419150e-01 1.031581e-02 5.797170e-03 9.999299e-01 4.291335e+00
9.999184e-01 3.088363e-03 -1.239599e-02 -2.812195e-01 -3.174350e-03 9.999710e-01 -6.922975e-03 -1.702743e-01 1.237425e-02 6.961759e-03 9.998991e-01 5.148987e+00
9.998890e-01 3.586305e-03 -1.446384e-02 -3.281178e-01 -3.703403e-03 9.999605e-01 -8.077186e-03 -1.986703e-01 1.443430e-02 8.129853e-03 9.998627e-01 6.007777e+00
9.998551e-01 4.078705e-03 -1.652913e-02 -3.749547e-01 -4.231669e-03 9.999484e-01 -9.229794e-03 -2.270290e-01 1.649063e-02 9.298401e-03 9.998207e-01 6.865477e+00
9.998167e-01 4.566671e-03 -1.859652e-02 -4.218367e-01 -4.760342e-03 9.999347e-01 -1.038342e-02 -2.554151e-01 1.854788e-02 1.047004e-02 9.997731e-01 7.724036e+00
9.997738e-01 5.049868e-03 -2.066463e-02 -4.687329e-01 -5.289072e-03 9.999194e-01 -1.153730e-02 -2.838096e-01 2.060470e-02 1.164399e-02 9.997198e-01 8.582886e+00
9.997264e-01 5.527315e-03 -2.272922e-02 -5.155474e-01 -5.816781e-03 9.999025e-01 -1.268908e-02 -3.121547e-01 2.265686e-02 1.281782e-02 9.996611e-01 9.440275e+00
9.996745e-01 6.000540e-03 -2.479692e-02 -5.624310e-01 -6.345160e-03 9.998840e-01 -1.384246e-02 -3.405416e-01 2.471098e-02 1.399530e-02 9.995966e-01 1.029896e+01
9.996182e-01 6.468772e-03 -2.686440e-02 -6.093087e-01 -6.873365e-03 9.998639e-01 -1.499561e-02 -3.689250e-01 2.676374e-02 1.517453e-02 9.995266e-01 1.115757e+01
9.995562e-01 7.058450e-03 -2.894213e-02 -6.562052e-01 -7.530449e-03 9.998399e-01 -1.623192e-02 -3.973964e-01 2.882292e-02 1.644266e-02 9.994492e-01 1.201541e+01
9.995095e-01 5.595311e-03 -3.081450e-02 -7.018788e-01 -6.093682e-03 9.998517e-01 -1.610315e-02 -4.239119e-01 3.071983e-02 1.628303e-02 9.993953e-01 1.286965e+01
The common name for your "projective transformation" is homography. In a calibrated setup (i.e. if you know your camera's field of view or, equivalently, its focal length) a homography can be decomposed into 3D rotation and translation, the latter only up to scale. The decomposition algorithm additionally produces the normal to the 3D plane inducting the homography. The algorithm has up to 4 solutions, of which only one is feasible when you apply additional constraints, such as that the matched image points triangulate in front of the camera, and that the general direction of the translation match a known prior.
More information about the method is in a well-known paper by Malis and Vargas. There is an implementation in OpenCV, under the name decomposeHomographyMat.

Odd Number plots using levelplot and rasterVis

I'm using the rasterVis package and the levelplot function to plot seven rasters on a single plot.
Here is the layout I'm going for:
correct layout
I've achieved this using the following code:
png("E:/all_files/production/plots/for_final/hist_vis_split2.png",
width=6, height=9, units="in", res=72)
layout(matrix(c(1,1,2,3,4,5,6,7), 4, 2, byrow = T))
print(maurer+layer(sp.lines(sr)), split=c(2,1,3,4), more=TRUE)
print(nar.ccsm+layer(sp.lines(sr)), split=c(1,2,3,4), more=TRUE)
print(nar.gfdl+layer(sp.lines(sr)), split=c(3,2,3,4), more=TRUE)
print(bcsd.ccsm+layer(sp.lines(sr)), split=c(1,3,3,4), more=TRUE)
print(bcsd.gfdl+layer(sp.lines(sr)), split=c(3,3,3,4), more=TRUE)
print(bcca.ccsm+layer(sp.lines(sr)), split=c(1,4,3,4), more=TRUE)
print(bcca.gfdl+layer(sp.lines(sr)), split=c(3,4,3,4))
dev.off()
Besides being clunky and lacking control, this is still missing a main title and a single common colorkey for the entire image.
I would prefer to use the levelplot command. Below is the code I've used to plot all seven rasters in a single levelplot with a single colorkey. Unfortunately this does not have the correct layout:
incorrect layout
crop.stack <- stack(maurer, bcsd.ccsm.crop, bcsd.gfdl.crop, bcca.ccsm.crop,
bcca.gfdl.crop, nar.ccsm.crop, nar.gfdl.crop)
plot.names <- c("Maurer", "BCSD CCSM", "BCSD GFDL", "BCCA CCSM",
"BCCA GFDL", "NARCCAP CCSM", "NARCCAP GFDL")
png("E:/all_files/production/plots/for_final/hist_vis.png",
width=6, height=9, units="in", res=72)
hist <- levelplot(crop.stack, main="Historical Average Production Days",
col.regions=cols,
names.attr=plot.names,
scales=list(draw=F),
layout=c(2,4))
hist + layer(sp.lines(sr))
dev.off()
The solution here is close, but does not deal with and odd number of plots. How can I achieve the desired layout within the levelplot command?

Resources