読者です 読者をやめる 読者になる 読者になる

yukiのブログ

作ったものなど

pythonでスクリーンショットを正しくとる(Windows)

問題

pythonの画像処理モジュールPillowにはスクリーンショットをとる関数PIL.Imagegrab.grab()があります。しかしこれはWindowsの一部の環境だとうまく動きません。具体的には、スクリーンショットをとっても左上の部分しか記録されません。

from PIL import ImageGrab
img = ImageGrab.grab()
img.save("screenshot.png")

上のコードを実行すると以下の画像が保存されます。 f:id:e-yuki67:20170212152645p:plain

この画像は本来保存されるべき画像とは異なっています。 f:id:e-yuki67:20170212152635p:plain

少し調べたところ、Windowsのスケーリング機能(デスクトップで右クリック->ディスプレイ設定で見れる)を使っているのが原因なことが分かりました。この機能は解像度が高いディスプレイでウィンドウや文字を大きく表示するために使われる機能なのですが、OSの内部ではディスプレイの解像度を小さくして座標の計算などが行われているらしく、この機能を使っているとディスプレイの解像度を取得する関数が正しい解像度を返してくれないようです。

その結果として、例えばスケーリング倍率を1.5倍にしていると解像度が1/1.5=2/3になったものとして扱われ、左上の2/3の領域しかキャプチャされません。

解決法

さらに調べると同じ問題とその解決法をPillowのgithubリポジトリissueで見つけました。そこには正しくスクリーンショットを取るコードも書いてあり、自分の環境でもうまくいきました。

issueに書いてあるコードはグローバル変数を使っているのであまりきれいなコードとは言えなかったのですが、自分で書いて自分で使うコードに使うだけだったのでそのまま使いました。ディスプレイの本当の解像度を取得する方法があるはずですが、見つけることができませんでした。

動いたコードを書いておきます。実行にはpywin32というモジュールが必要ですが、このモジュールはpipからインストールできないようなので注意が必要です。ググればインストーラーが出てきます。

import win32gui
import win32ui
import win32con
from PIL import Image

SCREEN_WIDTH = 2160
SCREEN_HEIGHT = 1440
SCREEN_SCALING_FACTOR = 1.5

def screenshot():
    """ スクリーンショット撮ってそれを(Pillow.Imageで)返す """
    window = win32gui.GetDesktopWindow()
    window_dc = win32ui.CreateDCFromHandle(win32gui.GetWindowDC(window))
    compatible_dc = window_dc.CreateCompatibleDC()
    width = SCREEN_WIDTH
    height = SCREEN_HEIGHT
    bmp = win32ui.CreateBitmap()
    bmp.CreateCompatibleBitmap(window_dc, width, height)
    compatible_dc.SelectObject(bmp)
    compatible_dc.BitBlt((0, 0), (width, height), window_dc, (0, 0), win32con.SRCCOPY)
    img = Image.frombuffer('RGB', (width, height), bmp.GetBitmapBits(True), 'raw', 'BGRX', 0, 1)
    return img

成果物

この関数を使って出来上がったのがこれです。同じサイズのスクリーンショットを複数とるのに適しています。

github.com

オートマトンをpythonで書く

(非)決定性有限オートマトンチューリングマシンより真に弱い計算能力を持つというのはどのオートマトンの教科書にも書いてあることです。このことが意味するのは、オートマトンでできることは全てチューリングマシンでできるということです。ということでチューリングマシンである普通のコンピューターでオートマトンを動かすプログラムをpythonで書きました。3か月間オートマトンについての講義を受け、その期末試験の直後にプログラムを書き始めたので、驚くほど簡単に書けました。

github.com

続きを読む

VHDLの環境構築

学校の課題でVHDLを書きました。

そのためにQurtus PrimeをインストールしてQuartusとModelSimを使ったのですが、動作が遅かったり文字やボタンが小さかったりウィンドウを頻繁に切り替えたりする必要があったりと、とにかくストレスが溜まりました。

そこでVHDLファイルのシミュレーション/コンパイル環境を整えました。結構うまくできたと思うので書いておきます。

以下で説明することはQurtus Primeが必要なので、Qurtus PrimeがインストールできないMacではできません。またLinuxでの動作確認もしてません。

何ができるか

  • VHDLファイルをVisual Studio Codeで編集
  • キーボードショートカットでVHDLファイルをコンパイル/シミュレート
  • コンパイルエラーを一覧で表示し、エディタ上で赤線で強調
  • ModelSimのGUIからボタン一つでシミュレーションの結果をロード

前提条件

簡単にできると思うので省略します。

準備

github.com

  • 上のリポジトリをダウンロードする
  • ダウンロードしたフォルダでコマンド vlib work を実行
  • ダウンロードしたフォルダでVisual Studio Code を開く
  • VHDLファイルにコメントでコンパイルとシミュレーションの方法が書いてあるのでそれに従う

Visual Studio CodeにはVHDL用の拡張機能があるので、それをインストールすることもお勧めします。

作業の流れ

  • Visual Studio CodeでVHDLファイルを編集する
  • キーボードショートカットでコンパイルする
  • エラーが出たら、キーボードショートカットで一覧を出して確認し、修正
  • エラーが無かったら、キーボードショートカットでテストベンチを走らせる
  • ModelSimの画面からReloadボタンを押す
  • シミュレーションがうまくいったら、Quartusの画面からフルコンパイル

絵を描くプログラム

エクセルとシェルとHTMLで絵を描くことができて、コードを少量追加すれば好きなもので絵を描くこともできるプログラムを書きました。

github.com

このプログラムで何ができるかはgithubのREADMEに譲るとして、このプログラムの中身がどうなっているかここにまとめました。

続きを読む

日本語の文章を解析するためのクラス

前回作ったプログラムで青空文庫のテキストを普通の日本語の文章にすることに成功したので、それを解析するプログラムを書きました。長いプログラムなのでコピペ用のプログラムは張ってません。

github.com

動かす

demoフォルダに漱石の文章がいくつか入っており、demo.pyを実行するとがこれらの文章が解析されます。

>python demo.py
---------------------こころ.txt----------------------
文字数(空白含まず), 160230
空白文字数, 1241
文数, 5168
文の平均文字数, 31.244389
一番長い文の文字数, 148
一番長い文, "学問をやり始めた時に..."
段落数(見出し除く), 1218
段落の平均文字数, 131
見出しの数, 113
一番長い段落の文字数, 978
一番長い段落, " 私はしばらくそこに..."
--------------------------------------------------
---------------------それから.txt---------------------
文字数(空白含まず), 170294
空白文字数, 1503
文数, 6140
文の平均文字数, 27.979967
一番長い文の文字数, 226
一番長い文, "登山の途中雪崩れに圧..."
段落数(見出し除く), 1800
段落の平均文字数, 94
見出しの数, 110
一番長い段落の文字数, 902
一番長い段落, "「何故働かないつて、..."
--------------------------------------------------
--------------------イズムの功過.txt--------------------
...(略)
続きを読む

青空文庫のテキストを簡略化する

漱石没後100年ということで漱石の文章を解析してみようと思い立ちました。しかし青空文庫の文章にはルビや注があって解析ができる状態ではありません。また漱石の文章をなんの装飾もせず公開している物好きなサイトも見当たりません。

そこで解析のための下準備として、青空文庫のテキストファイルからルビや注を取り除き、さらに一文ごとに改行をいれて解析しやすくするプログラムを描きました。

github.com

めんどくさい部分が多かった割にプログラム的には大したことやってませんが、正規表現の練習になりました。

続きを読む

シェルで絵を描く

シェルには背景や文字の色を変える機能があります。通常はデフォルトの色が気に入らない場合に変更するのに使いますが、この機能を使って絵を描くプログラムを書きました*1

動かす

記事の最後にあるシェルスクリプトを保存し、実行権限を与えて実行すると、nyancatがシェルに現れます*2

f:id:e-yuki67:20161225193534p:plain

手持ちの画像で試す場合には、記事の最後にあるpythonソースコードを適当な名前(例えばshell.py)で保存して

python3 shell.py hoge.jpg -n 75

とすれば、 hoge.jpgを描くシェルスクリプトhoge.shが作られます。nオプションを使ってシェルで表示される画像の横幅を調節できます。

なお起動にはPillowという画像処理パッケージが必要です。以下のコマンドでインストールできます。

python3 -m pip install pillow

*1:BashZshでは256色使えるが、Bash on Windowsでは16色しか使えない。そのため生成されるスクリプトも色が変になる。

*2:シェルにコピペしてもうまく動かない。長すぎて一度に貼り付けられないようだ。

続きを読む