【问题标题】:How to takeout the average colour of a screnshot taken using OpenCV?如何取出使用 OpenCV 截取的屏幕截图的平均颜色?
【发布时间】:2022-11-18 04:09:18
【问题描述】:

我正在尝试开发一种根据显示器颜色更改 RGB LED 灯条的设备。为此,我计划截取屏幕并标准化/取显示器中各个像素颜色的平均值。我在标准化图像和取出图像的平均颜色时遇到问题。这是我正在使用的代码。

import numpy as np
import cv2
import mss
import time  


def getAverageColor(frame):
    (B, G, R) = 0, 0, 0
    for i in frame:
        for j in i:
            B += j[0]
            G += j[1]
            R += j[2]
    B /= len(frame) * len(frame[0])
    G /= len(frame) * len(frame[0])
    R /= len(frame) * len(frame[0])
    return (B, G, R)



with mss.mss() as sct:
    # Grab frames in an endless lopp until q key is pressed
        time.sleep(2)
        # Itterate the list of monitors, and grab one frame from each monitor (ignore index 0)
        for monitor_number, mon in enumerate(sct.monitors[1:]):
            monitor = {"top": mon["top"], "left": mon["left"], "width": mon["width"], "height": mon["height"], "mon": monitor_number}  # Not used in the example

            # Grab the data
            img = np.array(sct.grab(mon)) # BGRA Image (the format BGRA, at leat in Wiqndows 10).
            print(getAverageColor(img))
            # Show down-scaled image for testing
            # The window name is img0, img1... applying different monitors.
            cv2.imshow(f'img{monitor_number}', cv2.resize(img, (img.shape[1]//4, img.shape[0]//4)))
            key = cv2.waitKey(1)
            if key == ord('q'):
                break

cv2.destroyAllWindows()

该程序运行良好,但我想问一下是否有任何方法可以去除 openCV 本身的平均颜色,因为我的方法不是很好推荐,因为它的处理速度可能非常慢。不要添加这个,但代码也不是很准确。

【问题讨论】:

  • 作为 getAverageColor 的想法:return cv.cvtColor(frame, cv.COLOR_BGR2HSV)[0].mean()?这是更短的,试试看是否更快。要设置 LED,您不关心亮度,对吗?总是 100%?
  • 让我试一试并在最终代码上更新此线程。

标签: python python-3.x opencv image-processing


【解决方案1】:

我已经更新了函数 getAverageColor,想法是找到主色。 我相信这会提供更好的颜色选择。时间是个问题,我会更新以防我能找到让它更快的方法。

import pandas as pd
from scipy.cluster.vq import whiten
from scipy.cluster.vq import kmeans
# import matplotlib.pyplot as plt


def getAverageColor(frame):
  r = []
  g = []
  b = []
  print("Frames")
  for row in frame:
      for temp_r, temp_g, temp_b, temp in row:
          r.append(temp_r)
          g.append(temp_g)
          b.append(temp_b)
  
  df = pd.DataFrame({'r' : r, 'g' : g, 'b' : b})
    
  df['scaled_r'] = whiten(df['r'])
  df['scaled_b'] = whiten(df['b'])
  df['scaled_g'] = whiten(df['g'])
    
  cluster_centers, _ = kmeans(df[['scaled_r', 'scaled_b', 'scaled_g']], 3)
    
  dominant_colors = []
    
  r_std, g_std, b_std = df[['r', 'g', 'b']].std()
    
  for cluster_center in cluster_centers:
      red_scaled, green_scaled, blue_scaled = cluster_center
      dominant_colors.append((red_scaled * r_std / 255, green_scaled * g_std / 255, blue_scaled * b_std / 255))
  
  print("Dominant", dominant_colors)
  return(dominant_colors[0])
  # plt.imshow([dominant_colors])
  # plt.show()

【讨论】:

    【解决方案2】:

    在 Python 中使用列表和for 循环进行图像处理效率低、速度慢且容易出错。尝试使用 Numpy 或矢量化库,例如打开简历,scikit图像,棍棒或者PIL/枕头.

    制作一个从石灰绿到黄色的示例渐变图像图像,即没有蓝色、纯绿色和红色渐变,这将为我们提供简单、易于检查的方法:

    magick -size 256x256 gradient:lime-yellow png24:start.png
    

    现在使用 Numpy 获取所有三个通道的方法:

    import cv2
    import numpy as np
    
    # Load image
    im = cv2.imread('start.png')
    
    print(im.shape)       # prints (256, 256, 3)
    
    meanBlue  = np.mean(im[...,0])     # gets value=0
    meanGreen = np.mean(im[...,1])     # gets value=255.0
    meanRed   = np.mean(im[...,2])     # gets value=127.5
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-12-20
      • 1970-01-01
      • 2011-01-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多