关于#电脑#屏幕监控的问题,如何解决?

帮忙提供电脑显示屏监控源代码,当显示器监视的区域画面弹出线条,会声音告警。(如下图)

img

用于在电脑显示屏监控特定区域的画面,并在检测到线条时触发声音告警

import cv2
import numpy as np
import winsound

def monitor_screen(region):
    cap = cv2.VideoCapture(0)  # 打开摄像头或视频文件,0表示默认摄像头
    while True:
        ret, frame = cap.read()  # 读取视频帧
        if not ret:
            break
        
        # 提取监视区域的画面
        x1, y1, x2, y2 = region
        screen = frame[y1:y2, x1:x2]
        
        # 在监视区域中检测线条
        gray = cv2.cvtColor(screen, cv2.COLOR_BGR2GRAY)
        edges = cv2.Canny(gray, 50, 150)
        lines = cv2.HoughLinesP(edges, 1, np.pi / 180, threshold=100, minLineLength=100, maxLineGap=10)
        
        if lines is not None:
            # 若检测到线条,则触发声音告警
            winsound.Beep(1000, 500)  # 发出1000Hz的声音,持续500毫秒
        
        # 显示监视区域的画面
        cv2.imshow('Screen Monitoring', screen)
        
        if cv2.waitKey(1) == ord('q'):  # 按下 'q' 键退出程序
            break
    
    # 释放资源
    cap.release()
    cv2.destroyAllWindows()

# 指定监视区域的坐标(左上角和右下角坐标)
monitor_region = (100, 100, 400, 400)

# 开始监视
monitor_screen(monitor_region)

```python

注意,代码使用了OpenCV库进行图像处理和线条检测,并使用winsound库触发声音告警。你需要确保已安装了相应的库并进行适当的配置。

使用Java开发的屏幕监控案例源代码,可以实现鼠标,键盘的监听,可以通过该案例实现
屏幕监控他人电脑,和QQ的远程协助类似。
 
import java.awt.AWTException;
 
import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
 
import javax.imageio.ImageIO;
 
/**
 *使用Java截屏工具,不停的截取当前屏幕图片,图片不需保存直接以流的形式发送的监控端电脑上,并显示出来
  *控制端的鼠标和键盘的操作再发送的被控端并且执行从而实现屏幕监控
  *可以达到用一台电脑完全控制另外一台电脑
  */
public class Server{
    public static void main(String args[]) {
        SendScreenImg sender=new SendScreenImg();
        sender.changeServerPort(30009);//此处可以修改服务端口
        new Thread(sender).start();//打开图像传输服务
        OperateWindow operate=new OperateWindow();
//        operate.changeServerPort(30010);//此处可以修改服务端口
        new Thread(operate).start();//打开主机操控服务
        
        //***** 当然 服务器端的端口修改是随时都可以操作的 它实际上是关闭以前的端口 再开启一个新端口 *****//
    }
}
 
/**
 * @author LanXJ @doctime 2010-7-8
 * 开启一个设定端口的服务,该服务用于向客户端传送主机的屏幕信息,实现客户端对服务器端主机的监控
 * 实例化线程类后默认打开DEFAULT_SERVER_PORT=30011 端口实现监听
 * 可以通过changeServerPort改变监听端口,也可以通过getServerPort来查询当前监听端口
 */
class SendScreenImg implements Runnable{
 
    public static final int DEFAULT_SERVER_PORT=30011;
    private int serverPort;
    private Robot robot;
    private ServerSocket serverSocket;
    private Rectangle rect;
    private Dimension screen;
    private BufferedImage img;
    private Socket socket;
    private ZipOutputStream zip;
 
    public SendScreenImg() {
        this.serverPort=SendScreenImg.DEFAULT_SERVER_PORT;
 
        try {
            serverSocket = new ServerSocket(this.serverPort);
            serverSocket.setSoTimeout(86400000);
        } catch (IOException e1) {
            e1.printStackTrace();
        }
 
        try {
            robot = new Robot();
        } catch (AWTException e) {
            e.printStackTrace();
        }
        screen = Toolkit.getDefaultToolkit().getScreenSize();
        rect = new Rectangle(screen);
 
    }
    public void changeServerPort(int serverPort){
        if(this.serverPort==serverPort)return;
        this.serverPort=serverPort;
        try {
            this.serverSocket.close();
        } catch (Exception e) {}
        try {
            serverSocket = new ServerSocket(this.serverPort);
            serverSocket.setSoTimeout(86400000);
        } catch (IOException e1) {
            e1.printStackTrace();
        }
    }
    public int getServerPort(){
        return this.serverPort;
    }
 
    public void run() {
        while (true) {
             try {
                 System.out.println("等待接收截屏信息");
                 socket = serverSocket.accept();
                 zip = new ZipOutputStream(new DataOutputStream(socket.getOutputStream()));
                 zip.setLevel(9);//为后续的 DEFLATED 条目设置压缩级别 压缩级别 (0-9)
                 try {
                     img = robot.createScreenCapture(rect);
                     zip.putNextEntry(new ZipEntry("test.jpg"));
                     ImageIO.write(img, "jpg", zip);
                     if(zip!=null)zip.close();
                     System.out.println("被控端:connect");
                 } catch (IOException ioe) {
                     System.out.println("被控端:disconnect");
                 }
             } catch (IOException ioe) {
                 System.out.println("错误1");
             } finally {
                 if (socket != null) {
                     try {
                         socket.close();
                     } catch (IOException e) {
                     }
                 }
             }
         }
    }
}
 
/**
 * @author LanXJ @doctime 2010-7-8
 * 开启一个设定端口的服务,该服务用于接受客户端传来的操作字符串,实现对服务器端主机的操控
 * 实例化线程类后默认打开DEFAULT_SERVER_PORT=30012 端口实现监听
 * 可以通过changeServerPort改变监听端口,也可以通过getServerPort来查询当前监听端口
 */
class OperateWindow implements Runnable {
    public static final int DEFAULT_SERVER_PORT=30012;
    private int serverPort;
    private ServerSocket serverSocket;
    private Robot robot;
    public OperateWindow() {
        this.serverPort=OperateWindow.DEFAULT_SERVER_PORT;
        try {
            this.serverSocket = new ServerSocket(this.serverPort);
            this.serverSocket.setSoTimeout(86400000);
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            robot = new Robot();
        } catch (AWTException e) {
            e.printStackTrace();
        }
    }
    public void changeServerPort(int serverPort){
        if(this.serverPort==serverPort)return;
        this.serverPort=serverPort;
        try {
            this.serverSocket.close();
        } catch (Exception e) {}
        try {
            this.serverSocket = new ServerSocket(this.serverPort);
            this.serverSocket.setSoTimeout(86400000);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public int getServerPort(){
        return this.serverPort;
    }
 
    public void run() {
        while (true) {
            try {
                Socket socket = serverSocket.accept();
                //读取操作信息:120,200,InputEvent.BUTTON1_DOWN_MASK 全部是int类型
                InputStream is = socket.getInputStream();
                int r;
                String info = "";
                while ((r = is.read()) != -1) {
                    info += "" + (char) r;
                }
                System.out.println(info);
                is.close();
                if (info != null) {
                    String s[] = info.trim().split(",");
                    if ("mouseClicked".equals(s[0].trim())) {//operateStr Model: mouseClicked,x,y,type  
                        //由于加上单击事件后,鼠标按下并快速抬起 就设计到按下、抬起、单击 三个事件,将单击变为了双击 不合乎规范  所以 服务端并没有实现单击事件的监听,这里保留 不坐修改
                        int type = Integer.parseInt(s[s.length - 1].trim());
                        if (s.length == 4) {
                            int x = Integer.parseInt(s[1].trim());
                            int y = Integer.parseInt(s[2].trim());
                            robot.mouseMove(x, y);
                            robot.mousePress(type);
                            robot.mouseRelease(type);
                            System.out.println("ClientINFO:MOUSE move to "+x+","+y+" AND execute TYPE IS click "+type);
                        }
                    }else if("mousePressed".equals(s[0].trim())){//operateStr Model: mousePressed,x,y,type
                        int type = Integer.parseInt(s[s.length - 1].trim());
                        if (s.length == 4) {
                            int x = Integer.parseInt(s[1].trim());
                            int y = Integer.parseInt(s[2].trim());
                            robot.mouseMove(x, y);
                            robot.mousePress(type);
                            System.out.println("ClientINFO:MOUSE move to "+x+","+y+" AND execute TYPE IS press "+type);
                        }
                    }else if("mouseReleased".equals(s[0].trim())){//operateStr Model: mouseReleased,x,y,type
                        int type = Integer.parseInt(s[s.length - 1].trim());
                        if (s.length == 4) {
                            int x = Integer.parseInt(s[1].trim());
                            int y = Integer.parseInt(s[2].trim());
                            robot.mouseMove(x, y);
                            robot.mouseRelease(type);
                            System.out.println("ClientINFO:MOUSE move to "+x+","+y+" AND execute TYPE IS release  "+type);
                        }
                    }else if("mouseDragged".equals(s[0].trim())){//operateStr Model: mouseDragged,x,y,type
                        if (s.length == 4) {
                            int x = Integer.parseInt(s[1].trim());
                            int y = Integer.parseInt(s[2].trim());
                            robot.mouseMove(x, y);
                            System.out.println("ClientINFO:MOUSE move to "+x+","+y );
                        }
                    }else if("mouseMoved".equals(s[0].trim())){
                        if (s.length == 3) {
                            int x = Integer.parseInt(s[1].trim());
                            int y = Integer.parseInt(s[2].trim());
                            robot.mouseMove(x, y);
                            System.out.println("ClientINFO:MOUSE move to "+x+","+y);
                        }
                    }else if("keyPress".equals(s[0].trim())){
                        if(s.length==2){
                            int keycode=Integer.parseInt(s[1]);
                            robot.keyPress(keycode);
                        }
                    }else if("keyRelease".equals(s[0].trim())){
                        if(s.length==2){
                            int keycode=Integer.parseInt(s[1]);
                            robot.keyRelease(keycode);
                        }
                    }else if("keyTyped".equals(s[0].trim())){
                        if(s.length==2){
                            int keycode=Integer.parseInt(s[1]);
                            robot.keyPress(keycode);
                            robot.keyRelease(keycode);
                        }
                    }
                }
            } catch (IOException e) {
                System.out.println("error1");
            }
        }
    }
}
 
 
 
 
--------------------------------------------------------------------------------
import java.awt.Dimension;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.concurrent.TimeUnit;
import java.util.zip.ZipInputStream;
 
import javax.imageio.ImageIO;
import javax.swing.*;
 
public class Client{
    public static void main(String args[]) {
 
        ServerGUI sendOrder=new ServerGUI("127.0.0.1", "实时操控");//被监控电脑的ip地址
        WriteGUI catchScreen=new WriteGUI(sendOrder);
        catchScreen.changePort(30009);//现在可以修改获取主机屏幕信息要访问的端口号
        new Thread(catchScreen).start();//启动线程
    }
}
 
/**
 * @author LanXJ @doctime 2010-7-8
 * 访问指定端口的服务,从服务器端读取图像流,生成(刷新)管理面板
 * 默认访问的端口为DEFAULT_PORT=30011 端口,
 * 可以通过changePort来改变访问端口,也可以通过getPort查看当前访问端口
 * 实例化线程类时需要传入一个ServerGUI类型的辅助窗体对象
 */
class WriteGUI extends Thread {
    public static final int DEFAULT_PORT=30011;
    private int port;
    private ServerGUI rec;
 
    /**
     * @param rec 辅助窗体对象,可通过实例化获得
     */
    public WriteGUI(ServerGUI rec) {
        this.port=WriteGUI.DEFAULT_PORT;
        this.rec = rec;
    }
    public void changePort(int port){
        this.port=port;
    }
    public int getPort(){
        return this.port;
    }
    public void run() {
        while (rec.getBoo()) {
            System.out.println((System.currentTimeMillis()/1000)%24%60);
            Socket socket = null;
            try {
                socket = new Socket(rec.getIP(), this.port);
                DataInputStream dis = new DataInputStream(socket.getInputStream());
                ZipInputStream zis = new ZipInputStream(dis);
                Image image = null;
                try {
                    zis.getNextEntry();// 读取下一个 ZIP 文件条目并将流定位到该条目数据的开始处
                    image = ImageIO.read(zis);// 把ZIP流转换为图片
                    rec.jlabel.setIcon(new ImageIcon(image));
                    rec.scroll.setViewportView(rec.jlabel);
                    rec.validate();
                } catch (IOException ioe) {}
                try{
//                    dis.close();
                    zis.close();
                }catch (Exception e) {}
                try {
                    TimeUnit.MILLISECONDS.sleep(50);// 接收图片间隔时间
                } catch (InterruptedException ie) {
                    ie.printStackTrace();
                }
            } catch (IOException ioe) {
            } finally {
                try {
                    socket.close();
                } catch (IOException e) {}
            }
        }
    }
}
 
/**
 * @author LanXJ @doctime 2010-7-8
 * 访问指定主机的指定端口,向主机发送实例化线程类时传入的操控命令,实现对该主机的操控
 * 默认访问服务端口为DEFAULT_PORT=30012 端口,主机IP为实例化线程类时传入的IP
 * 可以通过changePort和changeIP来修改访问的端口和主机
 * 也可以通过setOperateStr来设置需要发送的操控命令
 * 需要注意的是,修改访问端口或主机必须在线程启动之前修改,否则修改无效
 */
class SendOperate extends Thread {
    public static int DEFAULT_PORT=30012;
    private String ip;
    private int port;// 30012
    private String operateStr;
 
    public SendOperate(String ip, String operateStr) {
        this.ip = ip;
        this.port = SendOperate.DEFAULT_PORT;
        this.operateStr = operateStr;
    }
    public void setOperateStr(String operateStr){
        this.operateStr=operateStr;
    }
    public void changePort(int port){
        this.port=port;
    }
    public boolean changeIP(String ip){
        if(UtilServer.checkIp(ip)){
            this.ip=ip;
            return true;
        }
        return false;
    }
    public int getPort(){
        return this.port;
    }
    public String getIP(){
        return this.ip;
    }
    public void run() {
        if(this.operateStr==null||this.operateStr.equals("")){
            return;
        }
//        if(this.operateStr.trim().startsWith("mouseMoved")){
//            return;
//        }
        try {
            Socket socket = new Socket(this.ip, this.port);
            OutputStream os = socket.getOutputStream();
            os.write((this.operateStr).getBytes());
            os.flush();
            socket.close();
            System.out.println("INFO: 【SendOperate】ip=" + this.ip + ",port=" + this.port + ",operateStr="" + this.operateStr + "".");
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
}
 
/**
 * @author LanXJ @doctime 2010-7-8
 * 服务工具类
 */
class UtilServer{
    public static boolean checkIp(String ip){
        if(ip==null)return false;
        String []dps=ip.split("\.");
        if(dps.length!=4&&dps.length!=6)return false;
        boolean isIp=true;
        for (int i = 0; i < dps.length; i++) {
            try {
                int dp=Integer.parseInt(dps[i]);
                if(dp>255||dp< 0){
                    throw new RuntimeException("error IP");
                }
            } catch (Exception e) {
                isIp=false;
                break;
            }
        }
        return isIp;
    }
}
/**
 * @author LanXJ @doctime 2010-7-8
 * serverManage的辅助窗体,内部事件封装了sendOperate的实现
 */
class ServerGUI extends JFrame {
    private static final long serialVersionUID = 2273190419221320707L;
    JLabel jlabel;
    JScrollPane scroll;
    private String ip;
    private int port;
    private boolean boo;
    public boolean getBoo(){
        return this.boo;
    }
    public int getPort(){
        return this.port;
    }
    public void changePort(int port){
        this.port=port;
    }
    public String getIP(){
        return this.ip;
    }
    public boolean changeIP(String ip){
        if(UtilServer.checkIp(ip)){
            this.setTitle(this.getTitle().replace(this.ip, ip));
            this.ip=ip;
            return true;
        }
        return false;
    }
 
    protected ServerGUI(String IP, String sub) {
        this.boo = true;
        this.ip = IP;
        this.port=SendOperate.DEFAULT_PORT;
        this.setTitle("远程监控--IP:" + IP + "--主题:" + sub);
        this.jlabel = new JLabel();
        this.scroll = new JScrollPane();
        this.scroll.add(this.jlabel);
        scroll.addMouseListener(new MouseAdapter() {
            /*public void mouseClicked(MouseEvent e) {// getMousePosition()
                super.mouseClicked(e);
                //由于加上单击事件后,鼠标按下并快速抬起 就设计到按下、抬起、单击 三个事件,将单击变为了双击
                //所以不实现单击监听
                int x = (int) e.getX() + (int) ServerGUI.this.scroll.getHorizontalScrollBar().getValue();
                int y = (int) e.getY() + (int) ServerGUI.this.scroll.getVerticalScrollBar().getValue();
//                int type = e.getModifiers();//e.BUTTON1_MASK 或 e.BUTTON2_MASK 或 e.BUTTON3_MASK
                String operateStr ="mouseClicked,"+ x + "," + y + "," + e.getModifiers();
                
                SendOperate sender=new SendOperate(ServerGUI.this.ip, (operateStr));
                sender.changeIP(ServerGUI.this.ip);//同步ip
                sender.changePort(ServerGUI.this.port);//同步port
                sender.start();
            }*/
            
            public void mousePressed(MouseEvent e) {
                super.mousePressed(e);
                int x = (int) e.getX() + (int) ServerGUI.this.scroll.getHorizontalScrollBar().getValue();
                int y = (int) e.getY() + (int) ServerGUI.this.scroll.getVerticalScrollBar().getValue();
//                int type = e.getModifiers();//e.BUTTON1_MASK 或 e.BUTTON2_MASK 或 e.BUTTON3_MASK
                String operateStr ="mousePressed,"+ x + "," + y + "," + e.getModifiers();
                
                SendOperate sender=new SendOperate(ServerGUI.this.ip, (operateStr));
                sender.changeIP(ServerGUI.this.ip);//同步ip
                sender.changePort(ServerGUI.this.port);//同步port
                sender.start();
            }
            @SuppressWarnings("static-access")
            public void mouseReleased(MouseEvent e) {
                super.mouseReleased(e);
                int x = (int) e.getX() + (int) ServerGUI.this.scroll.getHorizontalScrollBar().getValue();
                int y = (int) e.getY() + (int) ServerGUI.this.scroll.getVerticalScrollBar().getValue();
//                int type = e.getModifiers();//e.BUTTON1_MASK 或 e.BUTTON2_MASK 或 e.BUTTON3_MASK
                String operateStr ="mouseReleased,"+ x + "," + y + "," + e.getModifiers();
                
                SendOperate sender=new SendOperate(ServerGUI.this.ip, (operateStr));
                sender.changeIP(ServerGUI.this.ip);//同步ip
                sender.changePort(ServerGUI.this.port);//同步port
                sender.start();
            }
        });
        scroll.addMouseMotionListener(new MouseMotionAdapter(){
            public void mouseDragged(MouseEvent e) {
                super.mouseDragged(e);
                int x = (int) e.getX() + (int) ServerGUI.this.scroll.getHorizontalScrollBar().getValue();
                int y = (int) e.getY() + (int) ServerGUI.this.scroll.getVerticalScrollBar().getValue();
                String operateStr ="mouseDragged,"+ x + "," + y + "," + e.getModifiers();
                
                SendOperate sender=new SendOperate(ServerGUI.this.ip, operateStr);
                sender.changeIP(ServerGUI.this.ip);//同步ip
                sender.changePort(ServerGUI.this.port);//同步port
                sender.start();
            }
            public void mouseMoved(MouseEvent e) {
                super.mouseMoved(e);
                int x = (int) e.getX() + (int) ServerGUI.this.scroll.getHorizontalScrollBar().getValue();
                int y = (int) e.getY() + (int) ServerGUI.this.scroll.getVerticalScrollBar().getValue();
                String operateStr ="mouseMoved,"+ x + "," + y;
                
                SendOperate sender=new SendOperate(ServerGUI.this.ip, (operateStr));
                sender.changeIP(ServerGUI.this.ip);//同步ip
                sender.changePort(ServerGUI.this.port);//同步port
                sender.start();
            }
        });
        this.addKeyListener(new KeyAdapter(){
            public void keyPressed(KeyEvent e) {
                super.keyPressed(e);
                String operateStr ="keyPress,"+ e.getKeyCode();
                
                SendOperate sender=new SendOperate(ServerGUI.this.ip, (operateStr));
                sender.changeIP(ServerGUI.this.ip);//同步ip
                sender.changePort(ServerGUI.this.port);//同步port
                sender.start();
            }
            public void keyReleased(KeyEvent e) {
                super.keyReleased(e);
                String operateStr ="keyReleas,"+ e.getKeyCode();
                
                SendOperate sender=new SendOperate(ServerGUI.this.ip, (operateStr));
                sender.changeIP(ServerGUI.this.ip);//同步ip
                sender.changePort(ServerGUI.this.port);//同步port
                sender.start();
            }
            public void keyTyped(KeyEvent e) {
//                super.keyTyped(e);
            }
        });
        this.add(scroll);
 
        this.setAlwaysOnTop(false);
        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        this.setBounds(100, 75, (int) screenSize.getWidth() - 200, (int) screenSize.getHeight() - 150);
        // this.setResizable(false);
        this.setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);// 关闭窗体不做任何事
        this.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {
                boo = false;
                ServerGUI.this.dispose();
                System.out.println("窗体关闭");
                System.gc();
            }
        });
        this.setVisible(true);
        this.validate();
 
    }
 
}

据我所知,目前没有可以监视屏幕区域变化的特地软件。但是有一些是监视网页上的内容变化的,可能对达到的你的目标有所帮助,你可以去参考下:
比如:监控网页内容,发现需要的内容后弹框和声音提醒:https://blog.csdn.net/lk_blog/article/details/48833785
监视显示器屏幕变化告警:https://download.csdn.net/download/hu_01_19/9561040

可以参考下面用python编写的电脑屏幕的监控示例

import cv2
import numpy as np
import pygame

# 初始化Pygame声音
pygame.mixer.init()
pygame.mixer.music.load('alarm.wav')

# 设置监控区域,这里设置为整个屏幕大小
monitor = {'top': 0, 'left': 0, 'width': 1920, 'height': 1080}

# 读入预设门限值,下面的值仅供参考
threshold = 200

# 读入图像颜色阈值,这里仅监控红色线条
lower_red = np.array([0, 0, 255])
upper_red = np.array([0, 0, 255])

# 打开屏幕作为视频捕捉对象
scr_cap = cv2.VideoCapture(0)

while True:
    # 读取窗口当前帧
    ret, frame = scr_cap.read()

    # 裁剪窗口以获取监控区域
    cropped = frame[monitor['top']:monitor['top'] + monitor['height'],
                      monitor['left']:monitor['left'] + monitor['width']]

    # 将选取的区域转换为HSV颜色空间
    hsv = cv2.cvtColor(cropped, cv2.COLOR_BGR2HSV)

    # 创建一个遮罩,用于检测红线条
    mask = cv2.inRange(hsv, lower_red, upper_red)

    # 对遮罩进行腐蚀和膨胀操作
    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
    mask = cv2.erode(mask, kernel)
    mask = cv2.dilate(mask, kernel)

    # 执行图像边缘检测
    edges = cv2.Canny(mask, threshold, threshold * 2)

    # 检测图像中的线条
    lines = cv2.HoughLinesP(edges, 1, np.pi/180, 100, minLineLength=100, maxLineGap=10)

    # 如果检测到线条,播放警报声音
    if lines is not None:
        pygame.mixer.music.play()

    # 显示结果
    cv2.imshow('monitor', cropped)
    cv2.imshow('edges', edges)
    cv2.imshow('mask', mask)

    # 等待退出
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

# 清理
scr_cap.release()
cv2.destroyAllWindows()

回答部分参考、引用ChatGpt以便为您提供更准确的答案:

根据您提供的图片,您需要帮助提供电脑显示屏监控的源代码,以实现当监视的区域画面弹出线条时能够触发声音告警。

要实现这样的功能,您可以使用计算机视觉技术来监测屏幕上的图像,并检测出线条的存在。以下是一个基本的思路和示例代码,供您参考:

  1. 安装必要的库和依赖:首先,您需要安装并配置适当的计算机视觉库,例如OpenCV和NumPy。这些库可以帮助您进行图像处理和分析。
  2. 捕获屏幕图像:使用适当的库和方法,您可以捕获屏幕上指定区域的图像。您可以指定监控的区域或全屏进行捕获。
  3. 图像处理和分析:对捕获的图像进行处理和分析,以检测线条的存在。您可以使用各种图像处理技术,例如边缘检测、霍夫变换等。根据您的需求,您可能需要进行一些图像预处理步骤,例如降噪或调整图像对比度。
  4. 线条检测和告警:通过对处理后的图像进行线条检测算法,可以判断是否存在线条。如果检测到线条,您可以触发声音告警,例如播放音频文件或发出声音提示。

需要注意的是,以上是一个基本的思路和示例代码,并不能覆盖所有的细节和具体实现。具体的代码实现可能会根据您使用的编程语言和库而有所不同。您可以根据自己的需求和实际情况进行代码的编写和调试。

另外,这只是一个简单的示例,实际的电脑显示屏监控系统可能需要更复杂的算法和逻辑来实现更准确的线条检测和告警功能。建议您在开发过程中参考相关的计算机视觉文档、示例和教程,以获得更详细的指导。