Skip to main content
Inspiring
September 1, 2023
Answered

Adobe script: Selecting the most prominent color from a PSD layer

  • September 1, 2023
  • 2 replies
  • 3676 views

Dear experts

Suppose I want to extract the most prominent color of an image or a photoshop layer, that is the color which is drawing the most attention, how is that possible?

I checked the following example -
Auto picking the most distinct accent color from a... - Adobe Support Community - 9875726

Here the code is picking up the average color of the image. Now this color is a mix of all the RGB components, but I want to get the most prominent color, not the average one.
Please check the attached picture; though purple is the most prominent color, the code is picking up the brown tone as the average color.

How can we enhance this?

This is the code from the above mentioned link -

 

 

var min_saturation = 50;

// create tmp layer and move it on top

app.activeDocument.artLayers.add();

if (app.activeDocument.activeLayer != app.activeDocument.layers[0]) 

    app.activeDocument.activeLayer.move(app.activeDocument.layers[0], ElementPlacement.PLACEBEFORE);

// stamp visible to tmp layer


var d = new ActionDescriptor();

d.putBoolean( charIDToTypeID( "Dplc" ), true );

executeAction( charIDToTypeID( "MrgV" ), d, DialogModes.NO );


// call hsb/hsl filter (rgb -> hsb)

var d = new ActionDescriptor();

d.putEnumerated( charIDToTypeID( "Inpt" ), charIDToTypeID( "ClrS" ), charIDToTypeID( "RGBC" ) );

d.putEnumerated( charIDToTypeID( "Otpt" ), charIDToTypeID( "ClrS" ), charIDToTypeID( "HSBl" ) ); 

executeAction( charIDToTypeID( "HsbP" ), d, DialogModes.NO );


// select "green" channel

app.activeDocument.activeChannels = [ app.activeDocument.channels[1] ];

// threshold 128 ==> saturation 50% or higher

var d = new ActionDescriptor();

d.putInteger( charIDToTypeID( "Lvl " ), min_saturation * 255/100 );

executeAction( charIDToTypeID( "Thrs" ), d, DialogModes.NO );


// selection from current channel

var r1 = new ActionReference();

r1.putProperty( charIDToTypeID( "Chnl" ), charIDToTypeID( "fsel" ) );

var d = new ActionDescriptor();

d.putReference( charIDToTypeID( "null" ), r1 );

var r2 = new ActionReference();

r2.putEnumerated( charIDToTypeID( "Chnl" ), charIDToTypeID( "Ordn" ), charIDToTypeID( "Trgt" ) );

d.putReference( charIDToTypeID( "T   " ), r2 );

executeAction( charIDToTypeID( "setd" ), d, DialogModes.NO );

// remove tmp layer

app.activeDocument.layers[0].remove();

// get average color for selection

var c = new SolidColor();

if (!get_average_color(c)) { alert("Something is wrong"); }

app.activeDocument.selection.deselect();

app.foregroundColor = c;

alert(c.rgb.red + " " +  c.rgb.green + " " + c.rgb.blue);

///////////////////////////////////////////////////////////////////////////////////

function get_average_color(color)
{
    try {
        
        var chnl = 3;
        if (app.activeDocument.mode == DocumentMode.CMYK) chnl = 4;

        if (app.activeDocument.mode == DocumentMode.GRAYSCALE) chnl = 1;

        var lm = new Array();
        var px = new Array();

        for (var i = 0; i < chnl; i++)
            {
            var hst = get_histogram(i+1);
            var l = 0;
            var p = 0;

            if (!hst) { return false; }

            for (var n in hst) { l += hst[n] * n; p += hst[n]; }  

            hst = null;

            lm.push(l);
            px.push(p);
            }

        if (app.activeDocument.mode == DocumentMode.RGB)
            {
            var r =lm[0]/px[0]; 
            var g =lm[1]/px[1]; 
            var b =lm[2]/px[2];

            with (color.rgb) { red = Math.round(r); green = Math.round(g); blue = Math.round(b); };
            }
        else if (app.activeDocument.mode == DocumentMode.LAB)
            {
            var _l = lm[0]/px[0] * 100/255; 
            var _a = lm[1]/px[1] - 128; 
            var _b = lm[2]/px[2] - 128;

            with (color.lab) { l = Math.round(_l); a = Math.round(_a); b = Math.round(_b); };
            }
        else if (app.activeDocument.mode == DocumentMode.CMYK)
            {
            var c = 100 - lm[0]/px[0] * 100/255; 
            var m = 100 - lm[1]/px[1] * 100/255; 
            var y = 100 - lm[2]/px[2] * 100/255;
            var k = 100 - lm[3]/px[3] * 100/255;

            with (color.cmyk) { cyan = Math.round(c); magenta = Math.round(m); yellow = Math.round(y); black = Math.round(k); };
            }
        else if (app.activeDocument.mode == DocumentMode.GRAYSCALE)
            {
            var _l = 100 - lm[0]/px[0] * 100/255; 

            with (color.gray) { gray = Math.round(_l);  };
            }
        else { alert("Unsupported color mode", "Error", true); return false; }

        return true;
        }
    catch (e) { alert(e); }
}

////////////////////////////////////////////////////////////
function get_histogram(n)
{
    try {
        var r = new ActionReference();
        r.putProperty(stringIDToTypeID("property"), stringIDToTypeID("histogram"));

        if (typeof(n) == "string")
            r.putName(stringIDToTypeID("channel"), n);
        else
            {
            if (app.activeDocument.mode == DocumentMode.RGB)
                {
                switch (n)
                    {       
                    case -1: r.putEnumerated(stringIDToTypeID("document"), stringIDToTypeID("ordinal"), stringIDToTypeID("targetEnum")); break;

                    case 0:  r.putEnumerated(stringIDToTypeID("channel"), stringIDToTypeID("channel"), stringIDToTypeID("RGB"  )); break;
                    case 1:  r.putEnumerated(stringIDToTypeID("channel"), stringIDToTypeID("channel"), stringIDToTypeID("red"  )); break;
                    case 2:  r.putEnumerated(stringIDToTypeID("channel"), stringIDToTypeID("channel"), stringIDToTypeID("green")); break;
                    case 3:  r.putEnumerated(stringIDToTypeID("channel"), stringIDToTypeID("channel"), stringIDToTypeID("blue" )); break;
   
                    default: r.putEnumerated(stringIDToTypeID("channel"), stringIDToTypeID("ordinal"), stringIDToTypeID("targetEnum")); break;
                    }
                }
            else if (app.activeDocument.mode == DocumentMode.LAB)
                {
                switch (n)
                    {
                    case -1: 
                    case 0:  r.putEnumerated(stringIDToTypeID("channel"), stringIDToTypeID("channel"), stringIDToTypeID("lab"      )); break;
                    case 1:  r.putEnumerated(stringIDToTypeID("channel"), stringIDToTypeID("channel"), stringIDToTypeID("lightness")); break;
                    case 2:  r.putEnumerated(stringIDToTypeID("channel"), stringIDToTypeID("channel"), stringIDToTypeID("a"        )); break;
                    case 3:  r.putEnumerated(stringIDToTypeID("channel"), stringIDToTypeID("channel"), stringIDToTypeID("b"        )); break;
   
                    default: r.putEnumerated(stringIDToTypeID("channel"), stringIDToTypeID("ordinal"), stringIDToTypeID("targetEnum")); break;
                    }
                }
            else if (app.activeDocument.mode == DocumentMode.CMYK)
                {
                switch (n)
                    {
                    case -1: r.putEnumerated(stringIDToTypeID("document"), stringIDToTypeID("ordinal"), stringIDToTypeID("targetEnum")); break;

                    case 0:  r.putEnumerated(stringIDToTypeID("channel"), stringIDToTypeID("channel"), stringIDToTypeID("CMYK"   )); break;
                    case 1:  r.putEnumerated(stringIDToTypeID("channel"), stringIDToTypeID("channel"), stringIDToTypeID("cyan"   )); break;
                    case 2:  r.putEnumerated(stringIDToTypeID("channel"), stringIDToTypeID("channel"), stringIDToTypeID("magenta")); break;
                    case 3:  r.putEnumerated(stringIDToTypeID("channel"), stringIDToTypeID("channel"), stringIDToTypeID("yellow" )); break;
                    case 4:  r.putEnumerated(stringIDToTypeID("channel"), stringIDToTypeID("channel"), stringIDToTypeID("black"  )); break;
   
                    default: r.putEnumerated(stringIDToTypeID("channel"), stringIDToTypeID("ordinal"), stringIDToTypeID("targetEnum")); break;
                    }
                }
            else if (app.activeDocument.mode == DocumentMode.GRAYSCALE)
                {
                switch (n)
                    {
                    case -1: 
                    case 0:  r.putEnumerated(stringIDToTypeID("channel"),  stringIDToTypeID("channel"), stringIDToTypeID("black")); break;
   
                    default: r.putEnumerated(stringIDToTypeID("channel"), stringIDToTypeID("ordinal"), stringIDToTypeID("targetEnum")); break;
                    }
                }

            else { alert("Unsupported color mode", "Error", true); return null; }
            }

        var ret;

        try { ret = executeActionGet(r).getList(stringIDToTypeID("histogram")); } catch (e) { alert(e); return null; }

        var hist = new Array();
        for (var i = 0; i < 256; i++) hist.push(ret.getInteger(i));
        // var max = Math.max.apply(null, hist);
        // alert (avg(hist));
        return hist;
        }
    catch (e) { alert(e); return null; }
}

function avg(arr) {
    var sum = 0;
 
    // Iterate the elements of the array
    for (var i = 0; i < 256; i++) {
      sum += arr[i];
    }
 
    // Returning the average of the numbers
    return sum / arr.length;
  }

 

 

This topic has been closed for replies.
Correct answer jazz-y

This is quite a creative task that does not have an unambiguous solution unless a mathematically precise definition of what "most prominent color" means is given ¯\_(ツ)_/¯

 

The first thing that came to my mind was to reduce the image and use the color difference formula to calculate how much each color differs from the other. If the color difference between two pixels is less than a user-specified threshold (in this case DE_THRESHOLD = 15), then add 1 point to the pixel. Thus, the color with the highest score will be more prominent in the image.

 

var apl = new AM('application'),
    doc = new AM('document');
const DE_THRESHOLD = 15,
    RESIZE_TO = 35;
if (apl.getProperty('numberOfDocuments')) {
    var docRes = doc.getProperty('resolution'),
        docW = doc.getProperty('width') * docRes / 72,
        docH = doc.getProperty('height') * docRes / 72;
    doc.duplicate();
    doc.resize(docW > docH ? 'width' : 'height', RESIZE_TO)
    var f = new File(Folder.temp + '/colors.raw');
    doc.flatten();
    doc.saveToRAW(f);
    doc.close('no');
    var colors = findColors(f);
    f.remove();
    for (var i = 0; i < colors.length; i++) {
        colors[i][3] = 0;
        for (var x = 0; x < colors.length; x++) {
            if (x != i && dE(colors[i], colors[x]) <= DE_THRESHOLD) colors[i][3]++
        }
    }
    var result = 0,
        idx = null;
    for (var i = 0; i < colors.length; i++) {
        if (colors[i][3] >= result) { result = colors[i][3]; idx = i; }
    }
    var c = new SolidColor;
    c.rgb.red = colors[idx][0],
        c.rgb.green = colors[idx][1],
        c.rgb.blue = colors[idx][2];
    foregroundColor = c;
}
function findColors(f) {
    var content = '';
    if (f.exists) {
        f.open('r');
        f.encoding = "BINARY";
        content = f.read();
        f.close();
        f.remove();
        return colors = function (s) {
            var m = [],
                offset = 0;
            do {
                var c = [];
                for (i = 0; i < 3; i++) {
                    var k = s.charCodeAt(offset + i);
                    c.push(k)
                };
                m.push(c)
                offset += 3;
            } while (offset < s.length)
            return m;
        }(content);
    }
}
function dE(a, b) {
    return Math.sqrt(Math.pow(a[0] - b[0], 2) + Math.pow(a[1] - b[1], 2) + Math.pow(a[2] - b[2], 2));
}
function AM(target) {
    var s2t = stringIDToTypeID,
        t2s = typeIDToStringID,
        c2t = charIDToTypeID;
    target = target ? s2t(target) : null;
    this.getProperty = function (property, id, idxMode) {
        property = s2t(property);
        (r = new ActionReference()).putProperty(s2t('property'), property);
        id != undefined ? (idxMode ? r.putIndex(target, id) : r.putIdentifier(target, id)) :
            r.putEnumerated(target, s2t('ordinal'), s2t('targetEnum'));
        return getDescValue(executeActionGet(r), property)
    }
    this.hasProperty = function (property, id, idxMode) {
        property = s2t(property);
        (r = new ActionReference()).putProperty(s2t('property'), property);
        id ? (idxMode ? r.putIndex(target, id) : r.putIdentifier(target, id))
            : r.putEnumerated(target, s2t('ordinal'), s2t('targetEnum'));
        return executeActionGet(r).hasKey(property)
    }
    this.resize = function (dimension, value) {
        (d = new ActionDescriptor()).putUnitDouble(s2t(dimension), s2t("pixelsUnit"), value);
        d.putBoolean(s2t("constrainProportions"), true);
        d.putEnumerated(c2t("Intr"), s2t("interpolationType"), s2t("automaticInterpolation"));
        executeAction(s2t("imageSize"), d, DialogModes.NO);
    }
    this.flatten = function () {
        executeAction(s2t("flattenImage"), new ActionDescriptor(), DialogModes.NO);
    }
    this.saveToRAW = function (f) {
        (d = new ActionDescriptor()).putBoolean(s2t('copy'), true);
        (d1 = new ActionDescriptor()).putObject(s2t("as"), s2t("rawFormat"), d);
        d1.putPath(s2t("in"), f);
        executeAction(s2t("save"), d1, DialogModes.NO);
    }
    this.duplicate = function () {
        (r = new ActionReference()).putEnumerated(target, s2t("ordinal"), s2t("targetEnum"));
        (d = new ActionDescriptor()).putReference(s2t("null"), r);
        executeAction(s2t("duplicate"), d, DialogModes.NO);
    }
    this.close = function (yesNo) {
        (d = new ActionDescriptor()).putEnumerated(s2t("saving"), s2t("yesNo"), s2t(yesNo));
        executeAction(s2t("close"), d, DialogModes.NO);
    }
    function getDescValue(d, p) {
        switch (d.getType(p)) {
            case DescValueType.OBJECTTYPE: return { type: t2s(d.getObjectType(p)), value: d.getObjectValue(p) };
            case DescValueType.LISTTYPE: return d.getList(p);
            case DescValueType.REFERENCETYPE: return d.getReference(p);
            case DescValueType.BOOLEANTYPE: return d.getBoolean(p);
            case DescValueType.STRINGTYPE: return d.getString(p);
            case DescValueType.INTEGERTYPE: return d.getInteger(p);
            case DescValueType.LARGEINTEGERTYPE: return d.getLargeInteger(p);
            case DescValueType.DOUBLETYPE: return d.getDouble(p);
            case DescValueType.ALIASTYPE: return d.getPath(p);
            case DescValueType.CLASSTYPE: return d.getClass(p);
            case DescValueType.UNITDOUBLE: return (d.getUnitDoubleValue(p));
            case DescValueType.ENUMERATEDTYPE: return { type: t2s(d.getEnumerationType(p)), value: t2s(d.getEnumerationValue(p)) };
            default: break;
        };
    }
}

 

You can go further and compare groups of colors with maximum scores among themselves, finding the difference already among them (that is, find any desired number of color clusters). You can use other color models (for example, HSB to eliminate (or reduce) the influence of individual color components) and so on.

2 replies

jazz-yCorrect answer
Legend
September 1, 2023

This is quite a creative task that does not have an unambiguous solution unless a mathematically precise definition of what "most prominent color" means is given ¯\_(ツ)_/¯

 

The first thing that came to my mind was to reduce the image and use the color difference formula to calculate how much each color differs from the other. If the color difference between two pixels is less than a user-specified threshold (in this case DE_THRESHOLD = 15), then add 1 point to the pixel. Thus, the color with the highest score will be more prominent in the image.

 

var apl = new AM('application'),
    doc = new AM('document');
const DE_THRESHOLD = 15,
    RESIZE_TO = 35;
if (apl.getProperty('numberOfDocuments')) {
    var docRes = doc.getProperty('resolution'),
        docW = doc.getProperty('width') * docRes / 72,
        docH = doc.getProperty('height') * docRes / 72;
    doc.duplicate();
    doc.resize(docW > docH ? 'width' : 'height', RESIZE_TO)
    var f = new File(Folder.temp + '/colors.raw');
    doc.flatten();
    doc.saveToRAW(f);
    doc.close('no');
    var colors = findColors(f);
    f.remove();
    for (var i = 0; i < colors.length; i++) {
        colors[i][3] = 0;
        for (var x = 0; x < colors.length; x++) {
            if (x != i && dE(colors[i], colors[x]) <= DE_THRESHOLD) colors[i][3]++
        }
    }
    var result = 0,
        idx = null;
    for (var i = 0; i < colors.length; i++) {
        if (colors[i][3] >= result) { result = colors[i][3]; idx = i; }
    }
    var c = new SolidColor;
    c.rgb.red = colors[idx][0],
        c.rgb.green = colors[idx][1],
        c.rgb.blue = colors[idx][2];
    foregroundColor = c;
}
function findColors(f) {
    var content = '';
    if (f.exists) {
        f.open('r');
        f.encoding = "BINARY";
        content = f.read();
        f.close();
        f.remove();
        return colors = function (s) {
            var m = [],
                offset = 0;
            do {
                var c = [];
                for (i = 0; i < 3; i++) {
                    var k = s.charCodeAt(offset + i);
                    c.push(k)
                };
                m.push(c)
                offset += 3;
            } while (offset < s.length)
            return m;
        }(content);
    }
}
function dE(a, b) {
    return Math.sqrt(Math.pow(a[0] - b[0], 2) + Math.pow(a[1] - b[1], 2) + Math.pow(a[2] - b[2], 2));
}
function AM(target) {
    var s2t = stringIDToTypeID,
        t2s = typeIDToStringID,
        c2t = charIDToTypeID;
    target = target ? s2t(target) : null;
    this.getProperty = function (property, id, idxMode) {
        property = s2t(property);
        (r = new ActionReference()).putProperty(s2t('property'), property);
        id != undefined ? (idxMode ? r.putIndex(target, id) : r.putIdentifier(target, id)) :
            r.putEnumerated(target, s2t('ordinal'), s2t('targetEnum'));
        return getDescValue(executeActionGet(r), property)
    }
    this.hasProperty = function (property, id, idxMode) {
        property = s2t(property);
        (r = new ActionReference()).putProperty(s2t('property'), property);
        id ? (idxMode ? r.putIndex(target, id) : r.putIdentifier(target, id))
            : r.putEnumerated(target, s2t('ordinal'), s2t('targetEnum'));
        return executeActionGet(r).hasKey(property)
    }
    this.resize = function (dimension, value) {
        (d = new ActionDescriptor()).putUnitDouble(s2t(dimension), s2t("pixelsUnit"), value);
        d.putBoolean(s2t("constrainProportions"), true);
        d.putEnumerated(c2t("Intr"), s2t("interpolationType"), s2t("automaticInterpolation"));
        executeAction(s2t("imageSize"), d, DialogModes.NO);
    }
    this.flatten = function () {
        executeAction(s2t("flattenImage"), new ActionDescriptor(), DialogModes.NO);
    }
    this.saveToRAW = function (f) {
        (d = new ActionDescriptor()).putBoolean(s2t('copy'), true);
        (d1 = new ActionDescriptor()).putObject(s2t("as"), s2t("rawFormat"), d);
        d1.putPath(s2t("in"), f);
        executeAction(s2t("save"), d1, DialogModes.NO);
    }
    this.duplicate = function () {
        (r = new ActionReference()).putEnumerated(target, s2t("ordinal"), s2t("targetEnum"));
        (d = new ActionDescriptor()).putReference(s2t("null"), r);
        executeAction(s2t("duplicate"), d, DialogModes.NO);
    }
    this.close = function (yesNo) {
        (d = new ActionDescriptor()).putEnumerated(s2t("saving"), s2t("yesNo"), s2t(yesNo));
        executeAction(s2t("close"), d, DialogModes.NO);
    }
    function getDescValue(d, p) {
        switch (d.getType(p)) {
            case DescValueType.OBJECTTYPE: return { type: t2s(d.getObjectType(p)), value: d.getObjectValue(p) };
            case DescValueType.LISTTYPE: return d.getList(p);
            case DescValueType.REFERENCETYPE: return d.getReference(p);
            case DescValueType.BOOLEANTYPE: return d.getBoolean(p);
            case DescValueType.STRINGTYPE: return d.getString(p);
            case DescValueType.INTEGERTYPE: return d.getInteger(p);
            case DescValueType.LARGEINTEGERTYPE: return d.getLargeInteger(p);
            case DescValueType.DOUBLETYPE: return d.getDouble(p);
            case DescValueType.ALIASTYPE: return d.getPath(p);
            case DescValueType.CLASSTYPE: return d.getClass(p);
            case DescValueType.UNITDOUBLE: return (d.getUnitDoubleValue(p));
            case DescValueType.ENUMERATEDTYPE: return { type: t2s(d.getEnumerationType(p)), value: t2s(d.getEnumerationValue(p)) };
            default: break;
        };
    }
}

 

You can go further and compare groups of colors with maximum scores among themselves, finding the difference already among them (that is, find any desired number of color clusters). You can use other color models (for example, HSB to eliminate (or reduce) the influence of individual color components) and so on.

c.pfaffenbichler
Community Expert
Community Expert
September 2, 2023

Neat, @jazz-y ! 

 

@nirmalya123 , the following Script would get you an alert of the number on not completely transparent pixels of the pixel layers (except the Background Layer). 

// 2023, use it at your own risk;
if (app.documents.length > 0) {
var myDocument = activeDocument;
var theLayers = collectPixelLayers();
alert ("the layers and their number of not completely transparent pixels\n"+theLayers.join("\n"));
};
////// load transparency //////
function loadTransparencyAsSelection (theID, theInvert) {
    var idchannel = stringIDToTypeID( "channel" );
    var desc7 = new ActionDescriptor();
        var ref3 = new ActionReference();
        ref3.putProperty( idchannel, stringIDToTypeID( "selection" ) );
    desc7.putReference( stringIDToTypeID( "null" ), ref3 );
        var ref4 = new ActionReference();
        ref4.putEnumerated( idchannel, idchannel, stringIDToTypeID( "transparencyEnum" ) );
        ref4.putIdentifier( stringIDToTypeID( "layer" ), theID );
    desc7.putReference( stringIDToTypeID( "to" ), ref4 );
    desc7.putBoolean(charIDToTypeID("Invr"), theInvert);
executeAction( stringIDToTypeID( "set" ), desc7, DialogModes.NO );
};
////// collect layers //////
function collectPixelLayers () {
// the file;
var myDocument = app.activeDocument;
// get number of layers;
var ref = new ActionReference();
ref.putProperty(stringIDToTypeID('property'), stringIDToTypeID('numberOfLayers'));
ref.putEnumerated( charIDToTypeID("Dcmn"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") ); 
var applicationDesc = executeActionGet(ref);
var theNumber = applicationDesc.getInteger(stringIDToTypeID("numberOfLayers"));
// process the layers;
var theLayers = new Array;
for (var m = 0; m <= theNumber; m++) {
try {
var ref = new ActionReference();
ref.putIndex( charIDToTypeID( "Lyr " ), m);
var layerDesc = executeActionGet(ref);
var layerSet = typeIDToStringID(layerDesc.getEnumerationValue(stringIDToTypeID("layerSection")));
var isBackground = layerDesc.getBoolean(stringIDToTypeID("background"));
// if group collect values;
if (layerSet != "layerSectionEnd" && layerSet != "layerSectionStart" && isBackground != true) {
    if (layerDesc.getInteger(stringIDToTypeID("layerKind")) == 1) {
        var theName = layerDesc.getString(stringIDToTypeID('name'));
        var theID = layerDesc.getInteger(stringIDToTypeID('layerID'));
// get number of pixels;
        loadTransparencyAsSelection (theID, false);
        myDocument.quickMaskMode = true;
        var theHisto = myDocument.activeChannels[0].histogram;
        var thePixelNumber = 0;
        for (var x = 1; x < theHisto.length; x++) {
            thePixelNumber = thePixelNumber + theHisto[x];
        };
        myDocument.quickMaskMode = false;
        theLayers.push([theName, thePixelNumber])
    }
};
}
catch (e) {};
};
return theLayers
};

 

c.pfaffenbichler
Community Expert
Community Expert
September 1, 2023

Please post the image proper. 

 

»Color« is a problemtic term and I fear some people use it without a clear definition – which can naturally make it difficult to quantify. 

 

What do you imagine the »most prominent color« to be in that example? 

The yellow parts seem to be the most saturated ones but some people might consider some purple to be more »prominent« – in which case the next question would be: Which purple? 

Inspiring
September 1, 2023

Hi @c.pfaffenbichler 

It may not be the exact purple, but even something closer is fine. May be average value of the all purple hues. But I don't want the average valus of the entire picture for sure.

In the present code, we are reading the histograms of all the channels.

So basically we need to decode the histogram. What should be the logic?

 

Thanks

c.pfaffenbichler
Community Expert
Community Expert
September 1, 2023

But how can you quantify that? 

The purple is not the most saturated color, so how do you want to weigh hue against saturation and area and luminance etc.? 

 

I expect scientists working on animal visual perception (humans in particular, naturally) have devised methods for evaluating images in this regard but on this Forum you may not meet those …