Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
2
Help us understand the problem. What is going on with this article?
@TeppeiMIURA

Numpy で画像マスクを作るときは型に気をつける

More than 1 year has passed since last update.

やりたいこと

画像や動画の一部以外を黒く塗りつぶして切り抜きたい場合、画像のマスクを作成して、それを重ね合わせることで実現する。

元画像
lena.png
マスク済み画像
masked_image.png

失敗

Numpy を使って黒塗りしたい範囲は 0、切り抜きたい範囲は 1 とするマスクを作成。
行列の各要素をかけるとマスクできると思ったら、思ってたのと違う出力になった。

h_img, w_img = img.shape[:2]
mask = np.zeros((h_img, w_img, 3))
radius = int(h_img / 2)
center = radius
cv2.circle(mask, (center, center), radius, (1, 1, 1), thickness=-1, shift=0)
masked_img = img * mask

Numpy で作ったマスク (mask)
err_mask.png

マスク済み画像 (masked_img)
err_masked_image.png

原因と解決策

Numpy で行列を定義するとき、 dtype を指定しないとデフォルトでは float64 型になる。一方で、opencv の imread で読み込んだ画像は、その輝度によって、CV_8U や CV_16F、 CV_32F で読み込まれる(通常は CV_8U)。 CV_8U だと Numpy のデータ型では np.uint8 に対応している。
つまり、失敗した例では CV_8U の画像に対して、 float64 型のマスクをかけている。

Numpy で行列を定義するときに、型を np.uint8 に指定してやる。
できた。

mask = np.zeros((h_img, w_img, 3), dtype=np.uint8) # 型を uint8 に指定

マスク済み画像
masked_image.png

マスクを画像として表示してみると、真っ黒。
mask.png

所感

データ型の不一致という初歩的なミスだが、最近 python ばかり使っていて、型を意識する機会が減っているせいか、気がつくのに時間がかかった。
そもそも、 np.zeros で定義せずに、np.zeros_like を使って image の型含めて行列定義すればよかった。

2
Help us understand the problem. What is going on with this article?
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
TeppeiMIURA
いい歳して大学院生やってる名古屋人。

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
2
Help us understand the problem. What is going on with this article?