Divide the screen image into a grid of rectangles r-many, in n by m "grid", each with a width (total width / n) and height (total height / m).
1a. Assign weight to high-profile areas of the screen, such as the left area.
1b. For each rectangle, assign pixels to the space (color, frequency)
For each rectangle R, frequency distribution f_R and weight W_R:
2a. Determine the color of the i-th circuit (for example, i = 1 background color) by scanning the "upper frequency", "second frequency" (that is, f_R [i ,:]) for each block.
2b. For each, I put it in the score table (color_i, score), where score = f_R [i, "frequency"] * W_R
2c. The best scorer for everyone I will be the i-th color of the scheme.
Theoretically, if you have a lot of “blue on white” or “red on black”, you should get white primary, blue secondary or black primary, red secondary, for example.
For your text color, either base it directly on calculating the background color, or select a secondary color, and if the V HSV difference is too low, set the color from the calculated color of the circuit, but increase the V value.
pseudo code:
float[][] weights = { { 1.0, 3.0, 5.0, 5.0, 3.0, 1.0, 1.0, 1.0, 1.0 }, { 2.0, 6.0, 7.0, 7.0, 6.0, 2.0, 3.0, 3.0, 2.0 }, { 2.0, 8.0, 9.0, 9.0, 7.0, 3.0, 6.0, 6.0, 3.0 }, { 2.0, 8.0, 9.0, 9.0, 7.0, 2.0, 3.0, 3.0, 2.0 }, { 2.0, 7.0, 9.0, 9.0, 7.0, 2.0, 1.0, 1.0, 1.0 }, { 2.0, 6.0, 7.0, 7.0, 6.0, 2.0, 3.0, 3.0, 1.0 }, { 1.0, 3.0, 5.0, 5.0, 3.0, 2.0, 6.0, 6.0, 2.0 }, { 1.0, 1.0, 2.0, 2.0, 1.0, 2.0, 6.0, 6.0, 2.0 }, { 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 3.0, 3.0, 1.0 } }; // Leave the following implementations to the imagination: void DivideImageIntoRegions( Image originalImage, out Image[][] regions ); void GetNthMostCommonColorInRegion( Image region, int n, out Color color ); TKey FindMaximum<TKey, TValue>( Map<TKey, TValue> map ); // The method: Color[] GetPrimaryScheme( Image image, int ncolors, int M = 9, int N = 9 ) { Color[] scheme = new Color[ncolors]; Image[][] regions = new Image[M][N]; DivideImageIntoRegions( image, regions ); for( int i = 0; i < ncolors; i++ ) { Map<Color, float> colorScores = new Map<Color, float>(); for( int m = 0; m < M; m++ ) for( int n = 0; n < N; n++ ) { Color theColor; GetNthMostCommonColorInRegion( region, i, theColor ); if( colorScores[theColor] == null ) { colorScores[theColor] = 0; } colorScores[theColor] += weights[m][n]; } scheme[i] = FindMaximum( colorScores ); } return scheme; }
Looking at the foregoing, it is clear that if there is an area with slight variability, it will have the same second color as the most common color. To adjust, the second most common color in this case can be zero, which could be protected from:
if( theColor != null ) continue; if( colorScores[theColor] == null ) { colorScores[theColor] = 0; } colorScores[theColor] += weights[m][n]; }