最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Python利用自帶模塊實(shí)現(xiàn)屏幕像素高效操作

 更新時(shí)間:2025年02月09日 11:03:47   作者:Jo喬戈里  
這篇文章主要為大家詳細(xì)介紹了Python如何利用自帶模塊實(shí)現(xiàn)屏幕像素高效操作,文中的示例代碼講解詳,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下

1、獲取屏幕放縮比例

from ctypes import wintypes
import ctypes
 
 
HORZRES = 8
LOGPIXELSX = 118
 
 
def get_scale_factor() -> float:
    user32 = ctypes.windll.user32
    gdi32 = ctypes.windll.gdi32
 
    # 定義 HDC 和 UINT 類(lèi)型
    HDC = wintypes.HDC
    UINT = wintypes.UINT
 
    # 定義 GetDC 和 GetDeviceCaps 的參數(shù)類(lèi)型和返回類(lèi)型
    user32.GetDC.argtypes = [wintypes.HWND]
    user32.GetDC.restype = HDC
 
    gdi32.GetDeviceCaps.argtypes = [HDC, UINT]
    gdi32.GetDeviceCaps.restype = wintypes.INT
 
    # 獲取設(shè)備上下文
    dc = user32.GetDC(None)
    widthScale = gdi32.GetDeviceCaps(dc, HORZRES)
    width = gdi32.GetDeviceCaps(dc, LOGPIXELSX)
    scale = width / widthScale
    return scale

2、獲取屏幕指定坐標(biāo)處像素顏色

import ctypes
from ctypes import wintypes
from typing import Sequence, Generator
 
 
user32 = ctypes.windll.user32
gdi32 = ctypes.windll.gdi32
 
# 定義類(lèi)型
HWND = wintypes.HWND
HDC = wintypes.HDC
HBITMAP = wintypes.HBITMAP
 
 
class BITMAPINFOHEADER(ctypes.Structure):
    _fields_ = [
        ("biSize", wintypes.DWORD),
        ("biWidth", wintypes.LONG),
        ("biHeight", wintypes.LONG),
        ("biPlanes", wintypes.WORD),
        ("biBitCount", wintypes.WORD),
        ("biCompression", wintypes.DWORD),
        ("biSizeImage", wintypes.DWORD),
        ("biXPelsPerMeter", wintypes.LONG),
        ("biYPelsPerMeter", wintypes.LONG),
        ("biClrUsed", wintypes.DWORD),
        ("biClrImportant", wintypes.DWORD)
    ]
 
class BITMAPINFO(ctypes.Structure):
    _fields_ = [
        ("bmiHeader", BITMAPINFOHEADER),
        ("bmiColors", wintypes.DWORD * 3)
    ]
 
 
def get_pixel_color(coords: Sequence[tuple[int, int]], hwnd: HWND) -> Generator[tuple[int, int, int], None, None]:
    rect = wintypes.RECT()
    user32.GetClientRect(hwnd, ctypes.byref(rect))
    width = rect.right - rect.left
    height = rect.bottom - rect.top
 
    # 創(chuàng)建內(nèi)存設(shè)備上下文
    hdc_src = user32.GetDC(hwnd)
    hdc_dst = gdi32.CreateCompatibleDC(hdc_src)
    bmp = gdi32.CreateCompatibleBitmap(hdc_src, width, height)
    gdi32.SelectObject(hdc_dst, bmp)
 
    # 使用 BitBlt 復(fù)制窗口內(nèi)容到內(nèi)存設(shè)備上下文
    gdi32.BitBlt(hdc_dst, 0, 0, width, height, hdc_src, 0, 0, 0x00CC0020)  # SRCCOPY
 
    # 獲取位圖信息
    bmi = BITMAPINFO()
    bmi.bmiHeader.biSize = ctypes.sizeof(BITMAPINFOHEADER)
    bmi.bmiHeader.biWidth = width
    bmi.bmiHeader.biHeight = -height  # 負(fù)值表示自底向上
    bmi.bmiHeader.biPlanes = 1
    bmi.bmiHeader.biBitCount = 32
    bmi.bmiHeader.biCompression = 0
 
    # 創(chuàng)建緩沖區(qū)并獲取位圖數(shù)據(jù)
    buffer = ctypes.create_string_buffer(width * height * 4)
    gdi32.GetDIBits(hdc_dst, bmp, 0, height, buffer, ctypes.byref(bmi), 0)
 
    # 釋放資源
    gdi32.DeleteObject(bmp)
    gdi32.DeleteDC(hdc_dst)
    user32.ReleaseDC(hwnd, hdc_src)
 
    # 遍歷指定坐標(biāo)并返回像素顏色
    for x, y in coords:
        if 0 <= x < width and 0 <= y < height:
            offset = (y * width + x) * 4
            color = buffer[offset:offset + 4]
            yield color[2], color[1], color[0]  # BGR -> RGB
        else:
            yield (0, 0, 0)

3、一個(gè)簡(jiǎn)單的使用案例

from typing import Sequence, Generator, Tuple
from tkinter import ttk
import tkinter as tk
from ctypes import wintypes
import ctypes
import requests
from io import BytesIO
from PIL import Image, ImageTk
 
 
 
 
 
user32 = ctypes.windll.user32
gdi32 = ctypes.windll.gdi32
 
HWND = wintypes.HWND
HDC = wintypes.HDC
HBITMAP = wintypes.HBITMAP
 
 
class BITMAPINFOHEADER(ctypes.Structure):
    _fields_ = [
        ("biSize", wintypes.DWORD),
        ("biWidth", wintypes.LONG),
        ("biHeight", wintypes.LONG),
        ("biPlanes", wintypes.WORD),
        ("biBitCount", wintypes.WORD),
        ("biCompression", wintypes.DWORD),
        ("biSizeImage", wintypes.DWORD),
        ("biXPelsPerMeter", wintypes.LONG),
        ("biYPelsPerMeter", wintypes.LONG),
        ("biClrUsed", wintypes.DWORD),
        ("biClrImportant", wintypes.DWORD)
    ]
 
 
class BITMAPINFO(ctypes.Structure):
    _fields_ = [
        ("bmiHeader", BITMAPINFOHEADER),
        ("bmiColors", wintypes.DWORD * 3)
    ]
 
 
def get_pixel_color(coords: Sequence[Tuple[int, int]], hwnd: HWND) -> Generator[Tuple[int, int, int], None, None]:
    rect = wintypes.RECT()
    user32.GetClientRect(hwnd, ctypes.byref(rect))
    width = rect.right - rect.left
    height = rect.bottom - rect.top
 
    hdc_src = user32.GetDC(hwnd)
    hdc_dst = gdi32.CreateCompatibleDC(hdc_src)
    bmp = gdi32.CreateCompatibleBitmap(hdc_src, width, height)
    gdi32.SelectObject(hdc_dst, bmp)
 
    gdi32.BitBlt(hdc_dst, 0, 0, width, height, hdc_src, 0, 0, 0x00CC0020)  # SRCCOPY
 
    bmi = BITMAPINFO()
    bmi.bmiHeader.biSize = ctypes.sizeof(BITMAPINFOHEADER)
    bmi.bmiHeader.biWidth = width
    bmi.bmiHeader.biHeight = -height  # 負(fù)值表示自底向上
    bmi.bmiHeader.biPlanes = 1
    bmi.bmiHeader.biBitCount = 32
    bmi.bmiHeader.biCompression = 0
 
    buffer = ctypes.create_string_buffer(width * height * 4)
    gdi32.GetDIBits(hdc_dst, bmp, 0, height, buffer, ctypes.byref(bmi), 0)
 
    gdi32.DeleteObject(bmp)
    gdi32.DeleteDC(hdc_dst)
    user32.ReleaseDC(hwnd, hdc_src)
 
    for x, y in coords:
        print(x, y, width, height)
        if 0 <= x < width and 0 <= y < height:
            offset = (y * width + x) * 4
            color = buffer[offset:offset + 4]
            yield color[2], color[1], color[0]  # BGR -> RGB
        else:
            yield (0, 0, 0)
 
 
def get_window_handle(window):
    window_name = window._w
    if not window_name.startswith("."):
        window_name = "." + window_name
    
    hwnd = ctypes.windll.user32.FindWindowW(None, window.title())
    if not hwnd:
        raise ValueError("Cannot get the window handle.")
    return hwnd
 
def download_image(url):
    response = requests.get(url)
    if response.status_code == 200:
        return Image.open(BytesIO(response.content))
    else:
        raise Exception(f"Failed to download image: HTTP {response.status_code}")
 
def display_image_in_label(image):
    photo = ImageTk.PhotoImage(image)
    label = ttk.Label(root, image=photo)
    label.image = photo  # 保持對(duì) PhotoImage 的引用,防止被垃圾回收
    label.pack()
 
 
def show_color(event):
    hwnd = get_window_handle(root)
    x, y = event.x, event.y
    # 注意這里的坐標(biāo)是相對(duì)于窗口的坐標(biāo),且傳入get_pixel_color的應(yīng)該是包含多個(gè)坐標(biāo)點(diǎn)的序列
    # 此外,為了高效獲取同一個(gè)畫(huà)面多個(gè)點(diǎn)的顏色,此處我使用了生成器進(jìn)行懶加載,因此獲取數(shù)據(jù)時(shí)請(qǐng)完整遍歷迭代器
    result = get_pixel_color([(x, y)], hwnd)
    colors = [i for i in result]
    print(f"{event.x, event.y}: {colors}")
 
 
if __name__ == "__main__":
    root = tk.Tk()
    width, height = 900, 500
    screenwidth = root.winfo_screenwidth()
    screenheight = root.winfo_screenheight()
    geometry = '%dx%d+%d+%d' % (width, height, (screenwidth - width) / 2, (screenheight - height) / 2)
    root.title("測(cè)試樣例")
    root.geometry(geometry)
    root.bind("<Motion>", show_color)
 
    image_url = "https://ts1.cn.mm.bing.net/th/id/R-C.475631ce281b88c3cd465761b37c5256?rik=ZFMiTYFwaPypTQ&riu=http%3a%2f%2fpic.ntimg.cn%2ffile%2f20180102%2f21532952_215949247000_2.jpg&ehk=9NnCJ9JG44zfdF2%2fr373s25s68H9vxLvyfMsKgEzAwc%3d&risl=&pid=ImgRaw&r=0"
    try:
        img = download_image(image_url)
        display_image_in_label(img)
    except Exception as e:
        print(f"Error: {e}")
        ttk.Label(root, text="Failed to load image.").pack()
 
    root.mainloop()

4、總結(jié)

上述方法比通常使用PIL的Image.ImageGrab方法要高效非常多,因?yàn)镮mage.ImageGrab是基于IO截屏操作的,頻繁的IO操作使單純進(jìn)行屏幕像素訪(fǎng)問(wèn)十分低效。

而上述方法采用的是BitBlt。BitBlt 是一種高效的位圖操作方法,可以將窗口的內(nèi)容復(fù)制到內(nèi)存設(shè)備上下文中,然后通過(guò) GetPixel 或直接訪(fǎng)問(wèn)位圖數(shù)據(jù)來(lái)獲取像素顏色。就像素訪(fǎng)問(wèn)而言其性能顯著強(qiáng)于前者。更多關(guān)于Window的API操作詳見(jiàn)官方文檔:

Windows GDI) (位圖函數(shù) - Win32 apps | Microsoft Learn

到此這篇關(guān)于Python利用自帶模塊實(shí)現(xiàn)屏幕像素高效操作的文章就介紹到這了,更多相關(guān)Python屏幕像素操作內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • python實(shí)現(xiàn)A*尋路算法

    python實(shí)現(xiàn)A*尋路算法

    A*算法可以顯示尋路圖,兩點(diǎn)之間尋找最短路徑,本文使用Python實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-06-06
  • PYQT5 vscode聯(lián)合操作qtdesigner的方法

    PYQT5 vscode聯(lián)合操作qtdesigner的方法

    這篇文章主要介紹了PYQT5 vscode聯(lián)合操作qtdesigner的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-03-03
  • Python使用matplotlib顯示圖像實(shí)例

    Python使用matplotlib顯示圖像實(shí)例

    在Python項(xiàng)目中處理圖像數(shù)據(jù)之前,需要確保安裝了matplotlib庫(kù),它是一個(gè)用于繪制圖表和圖像顯示的工具,若尚未安裝,可以使用pip命令進(jìn)行安裝,安裝完成后,可以通過(guò)matplotlib的pyplot模塊讀取并顯示MNIST手寫(xiě)數(shù)據(jù)集中的圖像,若需要顯示灰度圖
    2024-10-10
  • Python中的is和id用法分析

    Python中的is和id用法分析

    這篇文章主要介紹了Python中的is和id用法,實(shí)例分析了is和id的功能及使用技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-01-01
  • 報(bào)錯(cuò)解決:Anaconda虛擬環(huán)境下使用uwsgi運(yùn)行uwsgi.ini報(bào)錯(cuò)ImportError問(wèn)題

    報(bào)錯(cuò)解決:Anaconda虛擬環(huán)境下使用uwsgi運(yùn)行uwsgi.ini報(bào)錯(cuò)ImportError問(wèn)題

    作者通過(guò)安裝和運(yùn)行uwsgi部署flask項(xiàng)目時(shí)遇到了各種問(wèn)題,最后通過(guò)修改uwsgi配置文件、卸載并重新安裝uwsgi以及使用conda安裝uwsgi解決了問(wèn)題
    2026-02-02
  • 圖解Python中深淺copy(通俗易懂)

    圖解Python中深淺copy(通俗易懂)

    這篇文章主要介紹了圖解Python中深淺copy(通俗易懂),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • 如何利用pandas將Excel轉(zhuǎn)為html格式

    如何利用pandas將Excel轉(zhuǎn)為html格式

    工作中經(jīng)常會(huì)遇到Excel轉(zhuǎn)為html格式這種需求,下面這篇文章主要給大家介紹了關(guān)于如何利用pandas將Excel轉(zhuǎn)為html格式的相關(guān)資料,主要利用的是pd.to_html,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2021-08-08
  • Python實(shí)現(xiàn)FTP上傳文件或文件夾實(shí)例(遞歸)

    Python實(shí)現(xiàn)FTP上傳文件或文件夾實(shí)例(遞歸)

    本篇文章主要介紹了Python實(shí)現(xiàn)FTP上傳文件或文件夾實(shí)例(遞歸),具有一定的參考價(jià)值,有興趣的可以了解一下。
    2017-01-01
  • TensorFlow索引與切片的實(shí)現(xiàn)方法

    TensorFlow索引與切片的實(shí)現(xiàn)方法

    這篇文章主要介紹了TensorFlow索引與切片的實(shí)現(xiàn)方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-11-11
  • appium中常見(jiàn)的幾種點(diǎn)擊方式

    appium中常見(jiàn)的幾種點(diǎn)擊方式

    本文主要介紹了appium中常見(jiàn)的幾種點(diǎn)擊方式,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-02-02

最新評(píng)論

靖远县| 肥乡县| 来凤县| 从化市| 台山市| 东海县| 汽车| 平南县| 丰县| 隆回县| 沿河| 周宁县| 子洲县| 乌审旗| 鹤壁市| 错那县| 涟源市| 柳州市| 西贡区| 兴安盟| 嵊州市| 阿合奇县| 濉溪县| 普安县| 高雄县| 丹阳市| 灵丘县| 化德县| 湟源县| 石嘴山市| 喀什市| 阿瓦提县| 元阳县| 安龙县| 舞钢市| 鞍山市| 高邑县| 佛坪县| 颍上县| 油尖旺区| 桑日县|