【C#】DispatcherTimerを即起動させる
10秒毎に○○したいという時DispatcherTimerを使うわけですが、Startメソッドを呼んで 10秒経ってからイベントが開始されます。そうではなくて、Startメソッドを呼んだ時に イベント開始となってほしかったのですが、以下のやり方でOKです。
// Intervalを0に指定で即起動する timer.Interval = new TimeSpan(0, 0, 0); timer.Start(); void timer_Tick(object sender, EventArgs e) { // ここで本来の間隔に指定しなおす ((Timer)sender).Interval = new TimeSpan(0, 0, 10); }
【Python】pillow-simdによる画像読み込みの高速化
ディープラーニングのモデルをネットから拾ってくると、画像読み込みにopencvが使われているケースやpillowが使われているケースがあります。自分は使い慣れている/速いという理由でopencvを使ってもらえると助かるのですが、pillowが使われているケースもあり、pillowはopencvと比較して画像読み込み時間が長く、学習に時間がかかって困る時があります。
pillow部分をopencvに書き直す手もありますが、それが面倒という場合もあり、pillow-simdというライブラリを使えばプログラムを書き換えることなく画像読み込みを高速化できると聞いたので試してみます。しかし、pillow-simdはWindowsをサポートしていないのか、インストールでエラーが出ましたが、issueに回避策を見つけた人がいるのでそれに倣いひとまずインストールして試します。
pip uninstall pillow pip install --upgrade pillow-simd --global-option="build_ext" --global-option="--disable-jpeg" --global-option="--disable-zlib"
4000×3000の画像を読み込んでみたところ、むしろopencvのimreadよりpillow-simdの方が速そうです。
import cv2 from PIL import Image import time start = time.time() image = Image.open('pic.bmp') # Case pillow-simd: time = 78msec #image = cv2.imread('pic.bmp') # Case opencv: time = 93msec end = time.time() print(str(end - start))
【Python】画像データ拡張ライブラリAlbumentationsを使ってみる
PyTorch版のYOLO v3を作っている人がいたので試してみようと思っています。 github.com
ただ、Trainにデータ拡張が入っていないのでデータ拡張ロジックを追加したいと思ったところ、 Albumentationsというライブラリを見つけました。 github.com
物体検出やセグメンテーションにも利用可能そうなので早速試してみました。 使い方は以下を実施すれば良さげです。
- Composeを作って、Composeの中に実施したいデータ拡張を記述
- Composeに画像、ラベル、クラスIDを含むディクショナリを投入
以下はComposeを作るコードになります。
from albumentations import Compose from albumentations.augmentations.transforms import Resize, HorizontalFlip, RandomSizedCrop, HueSaturationValue def get_compose(crop_min_max, image_height, image_width, hue_shift, saturation_shift, value_shift): # Resize image to (image_height, image_width) with 100% probability # Flip LR with 50% probability # Crop image and resize image to (image_height, image_width) with 100% probability # Change HSV from -hue_shift to +hue_shift and so on with 100% probability # Format 'pascal_voc' means label is given like [x_min, y_min, x_max, y_max] return Compose([Resize(image_height, image_width, p=1.0), HorizontalFlip(p=0.5), RandomSizedCrop(crop_min_max, image_height, image_width, p=1.0), HueSaturationValue(hue_shift, saturation_shift, value_shift, p=1.0)], bbox_params={'format':'pascal_voc', 'label_fields':['category_id']})
このComposeは以下のように使います。
# Image size for YOLO image_size = 416 # Crop 80 - 100% of image crop_min = image_size*80//100 crop_max = image_size crop_min_max = (crop_min, crop_max) # HSV shift limits hue_shift = 10 saturation_shift = 10 value_shift = 10 # Get compose compose = get_compose(crop_min_max, image_size, image_size, hue_shift, saturation_shift, value_shift) # image: numpy array like return value of cv2.imread # labels: bounding box lists like [[366.7, 80.84, 132.8, 181.84], [5.66, 138.95, 147.09, 164.88]] # classes: class of each bounding box like [0, 1] annotation = {'image': image, 'bboxes': labels, 'category_id': classes} # Do augmentation augmented = compose(**annotation) augmented_image = augmented['image'] augmented_labels = augmented['bboxes']
【C#】ToList()の挙動についての勘違い
ToList()が思ってた動作と違ったのでメモしておきます。
↓のようなクラスを作ります。
class MyClass { public MyClass() { var random = new Random(); Value = random.Next(100); } public int Value { get; set; } }
上記クラスを使って以下のようなコードを書いてしまっていました。 ToList()は新しいリストを作成するので、中身もコピーされると勝手に勘違いしてました。
var myClasses = new List<MyClass>(); for (int i = 0; i < 1000; ++i) { myClasses.Add(new MyClass()); } // リストからある条件を満たすものを取り出し、コピーしたつもりになっていた var selectedMyClasses = myClasses.Where(i => i.Value >= 50).ToList(); // 値を書き換えると selectedMyClasses[0].Value = 10000; // 元の中身が書き換わってるので、countは1と表示される int count = myClasses.Count(i => i.Value == 10000); Console.WriteLine(count);
中身もコピーしたいのであれば、MyClassにコピー用メソッドを加えて
class MyClass : ICloneable { public MyClass() { var random = new Random(); Value = random.Next(100); } public int Value { get; set; } public object Clone() { return MemberwiseClone(); } }
↓こんな感じに書くのでしょうか。。。
var myClasses = new List<MyClass>(); for (int i = 0; i < 1000; ++i) { myClasses.Add(new MyClass()); } var selectedMyClasses = myClasses.Where(i => i.Value >= 50).Select(i => (MyClass)i.Clone()).ToList(); selectedMyClasses[0].Value = 10000; int count = myClasses.Count(i => i.Value == 10000); Console.WriteLine(count);
当たり前という突っ込みを受けそうですが、他に同じ質問している人いたので若干ほっとしました。
【C#】System.IO.Compression.ZipFileクラスのCreateFromDirectoryメソッドはデフォルト設定だと日本語フォルダ名に非対応
アプリケーションでエラーが起きたら必要なログを全てフォルダに集めて、そのフォルダをzip化するということを やろうとしたら、フォルダ名に日本語が入っていると文字化けすることが分かりました。 解決策は以下に書かれていて、encodingにEncoding.GetEncoding("sjis")を指定すれば大丈夫でした。 System.IO.Compression.ZipFileクラスにて、日本語のディレクトリ名やファイル名を文字化けさせずに圧縮処理 · GitHub
【Visual Studio】NuGetを実行したら「'xxxxx' にはすでに 'NETStandard.Library' に対して定義された依存関係があります。」というエラーが出るときの対処法
下記記事にあるようにNuGetをアップデートするのが正解。 というか何故こんな意味不明なエラーメッセージ。。。 qiita.com
【OpenCV】OpenCV3以降でDense SIFTを使いたい
画像から特徴量抽出する方法として、Dense SIFTを使いたいと思ったのですが、何故かOpenCV2のあるバージョンで削除されてしまったようです。ただ幸いkeypointを指定することでDense SIFTを実施できるようなのでメモします(とはいえSIFTの特許の問題があるので2019年3月までは様子見、もしくは別の抽出器を利用でしょうか)。
# dense_feature_detector.py import cv2 class DenseFeatureDetector(object): def __init__(self, detector, step, scale, start): self._detector = detector self._step = step self._scale = scale self._start = start pass def detect(self, image): # Convert image to gray if it is color if len(image.shape) == 3: gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) else: gray_image = image # Create dense keypoints keypoints = self._create_keypoints(gray_image) _, features = self._detector.compute(image, keypoints) return keypoints, features def _create_keypoints(self, gray_image): keypoints = [] rows, cols = gray_image.shape for y in range(self._start, rows, self._step): for x in range(self._start, cols, self._step): keypoints.append(cv2.KeyPoint(float(x), float(y), self._scale)) return keypoints
# main.py import cv2 from dense_feature_detector import DenseFeatureDetector if __name__ == '__main__': image = cv2.imread('lenna.jpg') sift = cv2.xfeatures2d.SIFT_create() detector = DenseFeatureDetector(sift, step=15, scale=15, start=15) keypoints, features = detector.detect(image) dense_keypoints_on_image = cv2.drawKeypoints(image, keypoints, None) cv2.imwrite('dense.png', dense_keypoints_on_image)