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の画面からフルコンパイル

フォルダのサイズを表示するプログラム作った

この記事はIS17er Advent Calendarの18日目が空いていたので、「無いよりはなんかあった方がいいだろう」と思ってその日のうちに書かれたものです。
17日目の記事はこちら

Windows標準のエクスプローラはフォルダのサイズを表示してくれないので、目立たない名前のフォルダが数ギガバイトも食ってたりしても気づきくくて厄介です。
そこでフォルダのサイズを表示するプログラムを書きました。

[2017/1/13追記]
githubリポジトリ作りました。
github.com
以下の記事は2016/12/18時点でのプログラムについての記事となります。

参考資料

プログラムを作るのに使ったモジュールや関数はAutomate the Boring Stuff with Pythonに載っていたものが多いです。この本はアルゴリズムやデータ構造のことなど考えずに、「pythonでなんかやろう!」というコンセプトのもと書かれた本で、プログラミングやpythonの入門(≠ 情報科学の入門)として最適だと思います。オンラインでなら無料で読めるので気になった方はぜひ。

動かす

python3の標準モジュールだけを使っているのでpythonがあれば動きます。WindowsUbuntuで動くことを確認しましたが、Macではわかりません。
記事の一番下にあるコードをコピペして、FolderSizeExplorer.pyなどの名前で保存した後

python3 FolderSizeExplorer.py

とすれば、現在のフォルダの中身を探索してサイズ順に表示します。
そのあとはフォルダの名前を入れればフォルダを移動でき、qと入力すれば終了できます。

pオプションで最初に探索するフォルダを変更できます。フォルダの内容が多い場合には探索に時間がかかります(自分の環境では100GB使用済みのCドライブ全体を探索すると1分程度かかりました)。見えるファイル全てにアクセスしているのでエラーがたくさん出ますが、問題ありません。

> python .\FolderSizeExplorer.py -p ~
target folder : C:\Users\iiyuk
No saved shelve found.
Collectiong imformation about C:\Users\iiyuk. This may take some time...
Permission denied : C:\Users\iiyuk\AppData\Local\Application Data
Permission denied : C:\Users\iiyuk\AppData\Local\History
.
.
.
Permission denied : C:\Users\iiyuk\NetHood
Permission denied : C:\Users\iiyuk\PrintHood
Permission denied : C:\Users\iiyuk\Recent
Permission denied : C:\Users\iiyuk\SendTo
Permission denied : C:\Users\iiyuk\Templates
Permission denied : C:\Users\iiyuk\スタート メニュー
You can reduce errors by running script as administrator.
------------Contents of C:\Users\iiyuk------------
100.00%   34155.90MB All contents
 44.82%   15309.09MB .\Documents
 20.13%    6875.94MB .\OneDrive
 15.41%    5262.00MB .\AppData
 12.50%    4269.39MB .\Pictures
  5.49%    1874.84MB .\Downloads
  1.32%     451.81MB .\.PyCharm2016.2
  0.22%      75.02MB .\.vscode
  0.05%      18.62MB Files in this folder
  0.05%      16.00MB .\.nuget
  0.01%       3.08MB .\3D Objects
  0.00%       0.05MB .\.ipython
  0.00%       0.04MB .\.matplotlib
  0.00%       0.02MB .\.pylint.d
  0.00%       0.01MB .\Desktop
  0.00%       0.01MB .\Favorites
  0.00%       0.00MB .\Searches
  0.00%       0.00MB .\Links
  0.00%       0.00MB .\Videos
  0.00%       0.00MB .\Music
  0.00%       0.00MB .\Contacts
  0.00%       0.00MB .\Saved Games
  0.00%       0.00MB .\.ssh
  0.00%       0.00MB .\.config
  0.00%       0.00MB .\Templates
Enter folder name. (or q to quit) :

qを押して終了するときに、探索の結果を保存することができます。保存しておけば次回同じフォルダを表示しようとしたときにロードできます。

続きを読む

クリッカーゲームを攻略する

[2017/1/13追記]
githubリポジトリ作りました。
github.com
以下の記事は2016/12/11時点のプログラムについての記事です。

この記事はIS17er Advent Calendar11日目の記事として書かれたものです。
10日目の記事はこちら

Cookie Clickerに代表される、「クリックでポイントを獲得 -> アップグレードを購入 -> クリックでポイントを獲得 ->...」を繰り返してポイントを増やしていくゲームのことをクリッカーゲームといいます。単純極まりないクリッカーゲームを、放置しておくだけでそれなりの効率で攻略するために、クリックを記録して高速で再生する単純なプログラムを作ったので解説します。

何ができるか、できないか

  • クリックの記録・再生ができる。
  • 左クリック以外は記録できない。
  • 半透明のウィンドウをクリックして記録するので、記録してる間はゲームが進展しない。
  • クリックの座標と順番だけ記録し、クリック間の時間は記録しない。
  • フェイルセーフ(暴走したときに実行を止める処理)は無い。

ないないづくしですが、クリッカーゲームを攻略するには十分なはずです。

動かす

Windowsではpythonの標準ライブラリだけで動きますが、MacLinuxではpyautoguiというモジュールが必要なので入れてください。pyautoguiにはPillowも必要です。ちなみにpython3です。

sudo python3 -m pip install pillow
sudo python3 -m pip install pyautogui

ダウンロード・解凍したフォルダでコマンドプロンプトを開いて以下のコマンドを打つと説明が現れるので、それに従ってください。-nオプションは無くてもかまいません。

python record.py -n cookieBaker

クリックの記録が済んだら、以下のコマンドで記録を再生できます。

python play.py cookieBaker.py -d 10 -r 0.5

dオプションで記録を再生する時間を、rオプションでクリックから次のクリックまでの間を設定できます。クリックから次のクリックまでの間をあまり小さくしすぎるとうまく動きません(0,001ぐらいが限度)。

続きを読む