Java屏幕捕获 但是python

想学习一下屏幕捕获,不知道怎么下手,关于这部分的帖子比较少,也不完全

从这个老哥这里看见一个15年的帖子,改了下,不过还是在他的基础上

java实现屏幕捕捉程序_java捕捉游戏界面-CSDN博客

java捕获的效果图:

java代码:

import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;

import javax.swing.*;

public class WindowCapture extends JFrame implements ActionListener {
    private ScreenCaptureUtil scrCaptureUtil = null;
    private PaintCanvas canvas = null;
    private int FpsNum = 30; // 刷新率,默认30fps
    //虽然但是,用截图捕获来做视频捕获不知道是好是坏,但是有远程软件就这么干过

//    private String windowName = "";
    //需要指定捕获的窗口名称           这个真不知道怎么搞
//

    public WindowCapture(){
        super("捕获");
        init();
        Thread captureThread = new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    canvas.drawScreen();
                    try {
                        Thread.sleep(1000 / FpsNum); // 根据刷新率进行刷新
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        captureThread.start();
    }

    public void init(){

        scrCaptureUtil = new ScreenCaptureUtil();
        canvas = new PaintCanvas(scrCaptureUtil);
        Container c = this.getContentPane();
        //临时设置一个头部
        Panel head = new Panel();
        head.setLayout(new GridLayout());

        c.setLayout(new BorderLayout());
        c.add(canvas,BorderLayout.CENTER);

        JTextField fpsInput = new JTextField(FpsNum +" "); // 添加输入框,让用户输入刷新率
        JButton openfpsBt = new JButton("使用刷新率");


        c.add(head, BorderLayout.NORTH);
        //head放到北
        head.add(fpsInput);
        head.add(openfpsBt);
        openfpsBt.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                //更改刷新率
                FpsNum = Integer.parseInt(fpsInput.getText());

            }
        });
        this.setSize(600, 400);
        this.setVisible(true);
        this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

    }
    public void actionPerformed(ActionEvent e){
        canvas.drawScreen();
    }
    public static void main(String[] args){
        new WindowCapture();
    }
}

class ScreenCaptureUtil{
    private Robot robot = null;
    private Rectangle scrRect =null;

    public ScreenCaptureUtil(){
        try{
            robot = new Robot();
        }catch(Exception e){
            System.out.println(e.toString());
        }
        Dimension scrSize = Toolkit.getDefaultToolkit().getScreenSize();
        scrRect = new Rectangle(0,0,scrSize.width,scrSize.height);
    }
    public BufferedImage captureScreen(){
        BufferedImage scrImg = null;
        try{
            scrImg = robot.createScreenCapture(scrRect);
        }catch(Exception e){
            System.out.println(e.toString());
        }
        return scrImg;
    }
}

class PaintCanvas extends JPanel{
    private ScreenCaptureUtil scrCaptureUtil = null;
    private BufferedImage scrImg = null;

    public PaintCanvas(ScreenCaptureUtil scrCaptureUtil){
        this.scrCaptureUtil = scrCaptureUtil;
    }
    protected void paintComponent(Graphics g){
        if(scrImg !=null){
            int iWidth = this.getWidth();
            int iHeight = this.getHeight();
            g.drawImage(scrImg, 0, 0, iWidth, iHeight, 0,0,scrImg.getWidth(),scrImg.getHeight(),null);
        }
    }
    public void drawScreen(){
        Graphics g = this.getGraphics();
        scrImg=scrCaptureUtil.captureScreen();
        if(scrImg != null){
            this.paintComponent(g);
        }
        g.dispose();
    }
}

可是吧,我要的效果是直接截取窗口的内容而不是全屏,问了一下GPT(3.5),给出的答案要么就是报错,要么就是截取到的是窗口局部的图像

然后就想看看python怎么做吧

换语言就说明有障碍了,还是问GPT怎么写吧,我把我的要求发给GPT,然后得到了这个:

python窗口里的内容是倒过来的。。而且显示还不完全
 

 然后我让GPT重写,然后一直报错,然后一怒之下怒了一下,决定自己看看什么毛病

后来没看出什么,然后我就拿GPT的代码去问文心

简单说就是使用窗口句柄获取程序托管在系统上的图像内容

 

 了解到窗口句柄是个什么东西之后,就去找获取句柄的工具,在安装了Visual Studio之后在他的工具包里有一个spy++的软件,打开他,然后点击搜索-->查找窗口

 

 如果安装了Vs(紫色这个)的话可以直接使用Everything去搜索spy,或者去他的安装目录下面找(推荐直接搜)

打开以后: 点击 --   搜索-->查找窗口

出来这个窗口,然后把那个准星放到要查句柄的窗口上,他的句柄就会在下面显示

由于涉及到知识盲区了所以得让AI帮忙了

由于各个AI能力不同所以选了GPT3.5,文心3.5跟星火

让他们互相解决报错问题

python实现后效果图:

 

 成了

在窗口句柄填写那里,在spy++获取的窗口句柄,复制开头这些0后面第一个不是0的字符到最后一个,假如句柄是00010ABC,那么填写在py代码里的句柄就是0x10ABC,把前面那些0浓缩成0x

py代码:注意装模块 

import cv2
import numpy as np
import win32gui
import win32ui
import win32con
import time

# 窗口句柄,这里需要替换成你要捕获的窗口的实际句柄
hwnd = 0x2A086A # 填入你的窗口句柄

# 获取窗口的矩形区域
left, top, right, bottom = win32gui.GetWindowRect(hwnd)
width = right
height = bottom

# 创建与窗口区域大小相同的兼容DC和位图
hwndDC = win32gui.GetWindowDC(hwnd)
mfcDC = win32ui.CreateDCFromHandle(hwndDC)
saveDC = mfcDC.CreateCompatibleDC()
saveBitMap = win32ui.CreateBitmap()
saveBitMap.CreateCompatibleBitmap(mfcDC, width, height)
saveDC.SelectObject(saveBitMap)

# 创建窗口
cv2.namedWindow('Window Capture', cv2.WINDOW_NORMAL)  # 允许调整窗口大小

# 设置帧率和每秒捕获次数
capture_per_sec = 60  # 每秒捕获次数 (帧率)
interval = 1 / capture_per_sec  # 间隔时间
while True:
    # 将窗口内容复制到位图中
    result = win32gui.BitBlt(saveDC.GetSafeHdc(), 0, 0, width, height, hwndDC, 0, 0, win32con.SRCCOPY)
    # 获取位图句柄和位图信息
    bmp_info = saveBitMap.GetInfo()
    bmp_str = saveBitMap.GetBitmapBits(True)

    # 将位图数据转换为numpy数组
    img_array = np.frombuffer(bmp_str, dtype=np.uint8)
    img_array.shape = (bmp_info['bmHeight'], bmp_info['bmWidth'], 4)

    # OpenCV使用BGR顺序,但位图通常是BGRA,所以需要转换顺序
    img_array = cv2.cvtColor(img_array, cv2.COLOR_BGRA2BGR)
    # 缩放图像
    max_width = 800
    max_height = 500
    scale = min(max_width / width, max_height / height)
    width_scaled = int(width * scale)
    height_scaled = int(height * scale)
    dim = (width_scaled, height_scaled)
    img_scaled = cv2.resize(img_array, dim, interpolation=cv2.INTER_AREA)
    # 显示图像
    cv2.imshow('Window Capture', img_scaled)

    # 等待一定时间
    time.sleep(interval)

    # 按下 'q' 键退出循环
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break
    
    left, top, right, bottom = win32gui.GetWindowRect(hwnd)
    # width = right
    # height = bottom


    print(left, top, width, height)

# 关闭窗口并清理资源
cv2.destroyAllWindows()
win32gui.ReleaseDC(hwnd, hwndDC)
saveDC.DeleteDC()
mfcDC.DeleteDC()
saveBitMap.Delete()

 

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值