Help us understand the problem. What is going on with this article?

PythonでWindowsのスニッピングツールらしきものを実装してみた

More than 1 year has passed since last update.

概要

PythonでWindowsのスニッピングツールらしきもの(ドラッグ&ドロップで選択した領域を画像として保存するプログラム)を実装してみました.やや強引な実装なのかもしれませんが,ご容赦下さい.

Youtubeにプログラムが動作しているところをUPしたので,是非一度ご覧下さい.
https://www.youtube.com/watch?v=e2zePSUGwaA

動機

前回投稿した「Pythonでタイピングゲームをプレイしてみた」のプログラムを作成した際,スクリーン上でキャプチャしたい領域のピクセル座標を,直感的かつ動的に取得する方法を模索していたところ,Windowsのスニッピングツールのような形式が最適だと思ったので,Pythonで実装してみようと思いました.

環境

OS : Windows10
Python Version : 3.5.3

使用した主なライブラリ

PyQt5, Pillow, OpenCV

プログラムの動作

main.py
# -*- coding: utf-8 -*-

import sys
from PyQt5 import QtWidgets, QtCore, QtGui
import tkinter as tk
from PIL import ImageGrab, Image
import matplotlib.pyplot as plt
import numpy as np
import cv2

class MyWidget(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()
        root = tk.Tk()
        screen_width = root.winfo_screenwidth()
        screen_height = root.winfo_screenheight()
        self.setGeometry(0,0,screen_width, screen_height)
        self.setWindowTitle("")
        self.setWindowOpacity(0.3)
        QtWidgets.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.CrossCursor))
        self.setWindowFlags(QtCore.Qt.FramelessWindowHint)
        self.begin = QtCore.QPoint()
        self.end = QtCore.QPoint()

        print("Capture the screen...")
        self.show()

    def paintEvent(self, event):
        qp = QtGui.QPainter(self)
        qp.setPen(QtGui.QPen(QtGui.QColor("black"), 3))
        qp.setBrush(QtGui.QColor(128, 128, 255, 128))
        qp.drawRect(QtCore.QRect(self.begin, self.end))       

    def mousePressEvent(self, event):
        self.begin = event.pos()
        self.end = self.begin
        self.update()

    def mouseMoveEvent(self, event):
        self.end = event.pos()
        self.update()

    def mouseReleaseEvent(self, event):
        self.end = event.pos()
        self.close()

        x1 = min(self.begin.x(), self.end.x())
        y1 = min(self.begin.y(), self.end.y())
        x2 = max(self.begin.x(), self.end.x())
        y2 = max(self.begin.y(), self.end.y())

        img = ImageGrab.grab(bbox=(x1,y1,x2,y2))
        img.save("capture.png")
        img = cv2.cvtColor(np.array(img), cv2.COLOR_BGR2RGB)

        cv2.imshow('Captured Image', img)
        cv2.waitKey(0)
        cv2.destroyAllWindows()

if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    window = MyWidget()
    window.show()
    app.aboutToQuit.connect(app.deleteLater)
    sys.exit(app.exec_())


  1. PyQt5を使用して,背景を透過させたGUIをスクリーン全体を覆うように配置.
  2. マウス関連のイベントリスナーを用いて,GUI上でのドラッグに合わせてピクセル座標を取得し,それをもとに長方形を描画.
  3. ドロップ時,GUIを消去した後,PillowImageGrabを用いて,選択した領域をキャプチャし画像として保存.
  4. OpenCVを用いて,取得した画像を表示.

応用

  1. スクリーンキャプチャを起点とするプログラムと組み合わせる.
  2. 取得した座標を用いて何かする.

まとめ

PythonでWindowsのスニッピングツールらしきものを実装することができた.

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away