Уведомления

Группа в Telegram: @pythonsu

#1 Авг. 8, 2018 20:34:26

lllNF
Зарегистрирован: 2018-08-04
Сообщения: 9
Репутация: +  0  -
Профиль   Отправить e-mail  

Быстрое получение цвета пикселя с экрана

Нужно как можно быстрее получать информацию о цвете пикселя с экрана.
Благодаря каким библиотекам это можно реализовать? Желательно с примером кода. Спасибо.

Пока что пробую pyautogui.pixel() но он слишком медленный вот сам код

 import time
import pyautogui
from pynput import keyboard
pressD = False
pressF = False
pressJ = False
pressK = False
RUN = True
while RUN:
    #D
    colorD = pyautogui.pixel(210,610) #Получение цвета пикселя
    print("colorD = ",colorD[0]) #Значение RED канала пикселя
    if colorD[0] > 230:
        #спам клавиши "d"
        keyboard.Controller().press('d')
        pressD = True
        print("'D' Down")
    else:
        if pressD:
        #прекращение спама
            keyboard.Controller().release('d')
            pressD = False
            print("'D' UP")
    #F
    colorF = pyautogui.pixel(310,610) #Получение цвета пикселя
    print("color = ",colorF[2]) #Значение BLUE канала пикселя
    if colorF[2] > 230:
        #спам клавиши "f"
        keyboard.Controller().press('f')
        pressF = True
        print("'F' Down")
    else:
        if pressF:
        #прекращение спама
            keyboard.Controller().release('f')
            pressF = False
            print("'F' UP")
    #J
    colorJ = pyautogui.pixel(410,610) #Получение цвета пикселя
    print("color = ",colorJ[2]) #Значение BLUE канала пикселя
    if colorJ[2] > 230:
        #спам клавиши "j"
        keyboard.Controller().press('j')
        pressJ = True
        print("'J' Down")
    else:
        if pressJ:
        #прекращение спама
            keyboard.Controller().release('j')
            pressJ = False
            print("'J' UP")
    #K
    colorK = pyautogui.pixel(510,610) #Получение цвета пикселя
    print("color = ",colorK[0]) #Значение RED канала пикселя
    if colorK[0] > 230:
        #спам клавиши "k"
        keyboard.Controller().press('k')
        pressK = True
        print("'K' Down")
    else:
        if pressK:
            #прекращение спама
            keyboard.Controller().release('k')
            pressK = False
            print("'K' UP")

Код спамит клавиши D,F,J,K при правильном цвете соответствующих пикселей

Если быть точным, то мне нужно получение цвета 4 пикселей экрана не реже чем 60 раз в секунду (Суммарно в секунду не менее 240 значений)

Отредактировано lllNF (Авг. 10, 2018 12:06:56)

Офлайн

#2 Авг. 9, 2018 07:52:19

doza_and
От:
Зарегистрирован: 2010-08-15
Сообщения: 4138
Репутация: +  252  -
Профиль   Отправить e-mail  

Быстрое получение цвета пикселя с экрана

lllNF
но он слишком медленный
С чего вы решили что он медленный? Где код по которому вы сделали вывод что он медленный?

ps
Если надо быстро обрабатывать картинку, то практически никогда не работают с отдельными пикселами даже на С не говоря уже о питоне у которого просто циклы в сотни раз медленнее.



Офлайн

#3 Авг. 9, 2018 11:58:37

PEHDOM
Зарегистрирован: 2016-11-28
Сообщения: 2196
Репутация: +  294  -
Профиль   Отправить e-mail  

Быстрое получение цвета пикселя с экрана

lllNF код в студию потому как даже в pyautogui есть несколько способов получить цвет пиксела.



==============================
Помещайте код в теги:
[code python][/code]
Бериегите свое и чужое время.

Офлайн

#4 Авг. 10, 2018 12:07:23

lllNF
Зарегистрирован: 2018-08-04
Сообщения: 9
Репутация: +  0  -
Профиль   Отправить e-mail  

Быстрое получение цвета пикселя с экрана

Где код по которому вы сделали вывод что он медленный?
 import time
import pyautogui
from pynput import keyboard
pressD = False
pressF = False
pressJ = False
pressK = False
RUN = True
while RUN:
    #D
    colorD = pyautogui.pixel(210,610) #Получение цвета пикселя
    print("colorD = ",colorD[0]) #Значение RED канала пикселя
    if colorD[0] > 230:
        #спам клавиши "d"
        keyboard.Controller().press('d')
        pressD = True
        print("'D' Down")
    else:
        if pressD:
        #прекращение спама
            keyboard.Controller().release('d')
            pressD = False
            print("'D' UP")
    #F
    colorF = pyautogui.pixel(310,610) #Получение цвета пикселя
    print("color = ",colorF[2]) #Значение BLUE канала пикселя
    if colorF[2] > 230:
        #спам клавиши "f"
        keyboard.Controller().press('f')
        pressF = True
        print("'F' Down")
    else:
        if pressF:
        #прекращение спама
            keyboard.Controller().release('f')
            pressF = False
            print("'F' UP")
    #J
    colorJ = pyautogui.pixel(410,610) #Получение цвета пикселя
    print("color = ",colorJ[2]) #Значение BLUE канала пикселя
    if colorJ[2] > 230:
        #спам клавиши "j"
        keyboard.Controller().press('j')
        pressJ = True
        print("'J' Down")
    else:
        if pressJ:
        #прекращение спама
            keyboard.Controller().release('j')
            pressJ = False
            print("'J' UP")
    #K
    colorK = pyautogui.pixel(510,610) #Получение цвета пикселя
    print("color = ",colorK[0]) #Значение RED канала пикселя
    if colorK[0] > 230:
        #спам клавиши "k"
        keyboard.Controller().press('k')
        pressK = True
        print("'K' Down")
    else:
        if pressK:
            #прекращение спама
            keyboard.Controller().release('k')
            pressK = False
            print("'K' UP")

Отредактировано lllNF (Авг. 10, 2018 12:09:48)

Офлайн

#5 Авг. 10, 2018 14:10:23

PEHDOM
Зарегистрирован: 2016-11-28
Сообщения: 2196
Репутация: +  294  -
Профиль   Отправить e-mail  

Быстрое получение цвета пикселя с экрана

lllNF а у вас часом не венда? если венда то таки да он может работать медленно. Начнем с того что что у самого pyautogui нет метода pixel(), оно берет его из pyscreeze

 ....
try:
    import pyscreeze
    from pyscreeze import (center, grab, locate, locateAll, locateAllOnScreen,
        locateCenterOnScreen, locateOnScreen, pixel, pixelMatchesColor,
screenshot)
...
источник https://github.com/asweigart/pyautogui/blob/master/pyautogui/__init__.py
смотрим исходники pyscreeze https://github.com/asweigart/pyscreeze/blob/master/pyscreeze/__init__.py
 ....
def pixel(x, y):
    if sys.platform == 'win32':
        # On Windows, calling GetDC() and GetPixel() is twice as fast as using our screenshot() function.
        hdc = windll.user32.GetDC(0)
        color = windll.gdi32.GetPixel(hdc, x, y)
        # color is in the format 0xbbggrr https://msdn.microsoft.com/en-us/library/windows/desktop/dd183449(v=vs.85).aspx
        r = color % 256
        g = (color // 256) % 256
        b = color // (256 ** 2)
        return (r, g, b)
    else:
return screenshot().getpixel((x, y))
...
а у венды почемуто начмная с висты и выше с вклченным Windows Desktop Composition, GetPixel работает ну просто очень медленно. Хотя в коментах написано что GetPixel() работает в два раза быстрее чем screenshot().getpixel()
ps обсуждение сабжа на стекверфлов
https://stackoverflow.com/questions/3800458/quickly-getting-the-color-of-some-pixels-on-the-screen-in-python-on-windows-7
хотя ХЗ, вроде не так уж и медленно 0.003 сек у меня, по крайней мере



==============================
Помещайте код в теги:
[code python][/code]
Бериегите свое и чужое время.

Отредактировано PEHDOM (Авг. 10, 2018 14:26:09)

Офлайн

#6 Авг. 10, 2018 15:02:19

lllNF
Зарегистрирован: 2018-08-04
Сообщения: 9
Репутация: +  0  -
Профиль   Отправить e-mail  

Быстрое получение цвета пикселя с экрана

PEHDOM
lllNF а у вас часом не венда? если венда то таки да он может работать медленно.

Хорошо буду знать. Но есть ли способ более быстрого получения цвета пикселя для python 3.x?

Офлайн

#7 Авг. 10, 2018 15:21:21

PEHDOM
Зарегистрирован: 2016-11-28
Сообщения: 2196
Репутация: +  294  -
Профиль   Отправить e-mail  

Быстрое получение цвета пикселя с экрана

lllNF
Но есть ли способ более быстрого получения цвета пикселя для python 3.x?
давайте для начала все же определимся с вашей скоростью, с чего вы взяли что оно работает медленно? Имхо 0,003 секунды вполне достаточно для любого бота, или тогда хотябы выложите сколько у вас занимает времени эта процедура.
PS мда забыл что сам всю эту фигню отключаю, вобщем получение одного пиксела Гетпикселом:
тема Windows Aero с включенной композицией 0.02 сек
тема Windows Aero с выключенной композицией 0.004 сек

Всеравно две сотых секунды достаточно быстро как по мне, если вам не нужно попиксельно перебирать весь рабочий стол.



==============================
Помещайте код в теги:
[code python][/code]
Бериегите свое и чужое время.

Отредактировано PEHDOM (Авг. 10, 2018 16:01:06)

Офлайн

#8 Авг. 10, 2018 16:24:39

PEHDOM
Зарегистрирован: 2016-11-28
Сообщения: 2196
Репутация: +  294  -
Профиль   Отправить e-mail  

Быстрое получение цвета пикселя с экрана

lllNF
. Но есть ли способ более быстрого получения цвета пикселя для python 3.x?
Это неправильный вопрос, все зависит от задачи, если вам нужно таки один пиксел то всежи имхо быстрее чем GetPixel сделать это весьма трудно. Другое дело если нужно найти какойто пиксел на экране или перебрать несколько пикселов, тогда имеет смысл сделать скриншот и уже работать с ним. Например на выполнение PIL.ImageGrab.grab() уходит теже 0.02 секунды, но потом вы уже не теряете время, а просто перебиаете пикселы что вам нужно.
На одном пикселе разницы никакой, но напмриер на 4-х разница уже в 4 раза, так как на PIL.ImageGrab.grab() у вас уйдет 0.2 секунды, а на всю остальную математику десятытысячные доли, в тоже время на каждый GetPixel() у вас будет уходить по 0.02 секунды, а это уже почти 0.1 секунды.
В данном случае, не ГетПиксел медленный, а архитектура неправильная



==============================
Помещайте код в теги:
[code python][/code]
Бериегите свое и чужое время.

Отредактировано PEHDOM (Авг. 10, 2018 17:09:27)

Офлайн

#9 Авг. 10, 2018 18:33:47

lllNF
Зарегистрирован: 2018-08-04
Сообщения: 9
Репутация: +  0  -
Профиль   Отправить e-mail  

Быстрое получение цвета пикселя с экрана

PEHDOM
Да, для простого получения пикселя это занимает 0.003 сек. но в самом коде помимо этого есть много других команд, они тоже занимают время. Сверху оригинальных код, на одно выполнение которого уходит ~0.06 сек, а это много.

Как можно оптимизировать этот код? Я просто в этом деле ещё совсем зеленый

Офлайн

#10 Авг. 10, 2018 20:29:23

vic57
Зарегистрирован: 2015-07-07
Сообщения: 893
Репутация: +  126  -
Профиль   Отправить e-mail  

Быстрое получение цвета пикселя с экрана

lllNF
Как можно оптимизировать этот код?
попробуй QImage, там функции сишные
http://doc.qt.io/qt-5/qimage.html#pixel-1
типа так
 >>>from PyQt5 import Qt
>>> img = Qt.QImage(100,100,Qt.QImage.Format_RGB32)
>>> img.fill(Qt.QColor(100,150,200))
>>> pix = img.pixel(10,10)
>>> r,g,b = Qt.qRed(pix),Qt.qGreen(pix),Qt.qBlue(pix)
>>> r,g,b
(100, 150, 200)
>>> 
я бы через ctypes сделал, намного быстрее с однородными массивами работает

Отредактировано vic57 (Авг. 10, 2018 21:25:57)

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version