屋根材の判別してみた

1.    はじめに

こんにちは。エンジニア転職を目指して勉強中の建築板金職人です。

2. 目的

材質が似たような物や様々な形の屋根材があるので画像だけで本当に機械が判別出来るのか興味本位で作ってみました。判別する種類としましては① 縦平葺き ②コロニアル ③瓦の三種類の判別になります。本来もっと屋根材の種類はありますが、代表的な物と判別しやすいような三種類にしました。

屋根材の説明

①縦平葺き                                大きく分けると材質が金属の屋根で、屋根の中でも最近人気の材料になります。金属屋根の中でも横葺きや折半などありますが特徴としては、屋根の水上(雨が当たる一番上の部分)から水下まで一枚の材料で縦に繋ぎ合わせて貼る事によって雨水の侵入を防ぐような材料。

金属屋根-1

②スレート屋根 コロニアル                         ①の屋根の材料とは材質が変わりセメントを固めたような材料になります。特徴としてはカラーバリエーションが豊富なのと安価で木造住宅ではよく使われている。(今回はネットから画像を集めてくる関係上スレート屋根の中でもコロニアルという商品での判別になります)

屋根写真トップ-960x680

③  瓦屋根                                今回の屋根は住宅関係以外の方も知っている方が多いと思いますが瓦屋根になります。(材質は様々あるので瓦の一括りにしています。) 僕自身も瓦に関しては、あまり知識がなく瓦はほぼ施工しないので詳しくないです。屋根屋さんの括りになると思う方も多いと思いますが瓦に関しては瓦屋さんが施工する事が多く、屋根の中でもさらに瓦専門でやっている方が多いイメージです。

図4

3.   実行環境

環境  Python 3.8.8     Keras 2.4.4  Google Colaboratoryを使用

4. やったこと

①  ネットから写真を取得                         金属屋根、スレート、瓦など材質で調べてしまうと違うものも大量に取得してしまったため材料名など細かく検索ワードを設定し700枚程度画像を集める。

from icrawler.builtin import BingImageCrawler
import glob
 #検索リストの生成 
search_words = ["ガルバリウム 縦葺き","スレート屋根 コロニアル","瓦屋根 和瓦 洋瓦"]
dir_names = ["garibariumu tatebuki","sure-toyane koroniaru","kawarayane wagawara yougawara"]

for search_word,dir_name in zip(search_words,dir_names):
 # Bing用クローラーの生成
 bing_crawler = BingImageCrawler(
     downloader_threads=4,           # ダウンローダーのスレッド数
     storage={'root_dir': dir_name}) # ダウンロード先のディレクトリ名

 # クロール(キーワード検索による画像収集)の実行
 bing_crawler.crawl(
     keyword=search_word,   # 検索キーワード(日本語もOK)
     max_num=700)                    # ダウンロードする画像の最大枚数

② 取得した画像から屋根材ではない物を削除                細かく検索したものの違う画像も入っているので違うものを削除し400枚程度の画像が集まる。

③  集めた画像のパスとサイズを統一してく

import cv2
import numpy as np
import glob
kawara_paths = []
cls_labels = []
dir_names = ["garubariumutatebuki","sure-toyane koroniaru","kawarayane wagawara yougawara"]
#fish_pathsにスレート〜ガルバリムまでの、三つの画像を取得
for i,dir_name in enumerate(dir_names):
 dir_list = glob.glob("/content/drive/MyDrive/" + dir_name +"/*")
 kawara_paths += dir_list
 cls_labels  += [i]*len(dir_list)
#正解データが0〜2に設定

img_kawara = []

#画像を読み込み、サイズを統一しimg_fishに読み込む
for kawara_path in kawara_paths:
   img = cv2.imread(kawara_path)
   img = cv2.resize(img, (50,50))
   img_kawara.append(img)
 #学習ラベルがX 正解ラベルがY     
X = np.array(img_kawara)
y =  np.array(cls_labels)

④ 転移学習し判定させていく

学習データとテストデータにわけVGG16という学習モデルを使い学習させてく

import os
import cv2
import numpy as np
import matplotlib.pyplot as plt
from tensorflow.keras.utils import to_categorical
from tensorflow.keras.layers import Dense, Dropout, Flatten, Input
from tensorflow.keras.applications.vgg16 import VGG16
from tensorflow.keras.models import Model, Sequential
from tensorflow.keras import optimizers

rand_index = np.random.permutation(np.arange(len(X)))
X = X[rand_index]
y = y[rand_index]

# データの分割
X_train = X[:int(len(X)*0.8)]
y_train = y[:int(len(y)*0.8)]
X_test = X[int(len(X)*0.8):]
y_test = y[int(len(y)*0.8):]

# 正解ラベルをone-hotの形にします
y_train = to_categorical(y_train)
y_test = to_categorical(y_test)

# モデルにvggを使います
input_tensor = Input(shape=(50, 50, 3))
vgg16 = VGG16(include_top=False, weights='imagenet', input_tensor=input_tensor)

# vggのoutputを受け取り、2クラス分類する層を定義します
# その際中間層を下のようにいくつか入れると精度が上がります
top_model = Sequential()
top_model.add(Flatten(input_shape=vgg16.output_shape[1:]))
top_model.add(Dense(256, activation='relu'))
top_model.add(Dropout(0.5))
top_model.add(Dense(3, activation='softmax'))

# vggと、top_modelを連結します
model = Model(inputs=vgg16.input, outputs=top_model(vgg16.output))

# vggの層の重みを変更不能にします
for layer in model.layers[:19]:
   layer.trainable = False

# コンパイルします
model.compile(loss='categorical_crossentropy',
             optimizer=optimizers.SGD(lr=1e-4, momentum=0.9),
             metrics=['accuracy'])

# 学習を行います
history=model.fit(X_train, y_train, batch_size=50, epochs=30, validation_data=(X_test, y_test))
model.save('model.h5')

⑤  判別したものを返す

def pred_yane(img):
   img = cv2.resize(img, (50, 50))
   pred = np.argmax(model.predict(np.array([img])))
   
   return dir_names[pred]
   
 #Fred_gender関数に写真を渡して屋根材を予測 
img = cv2.imread(kawara_paths[i*50])
b,g,r = cv2.split(img) 
img = cv2.merge([r,g,b])
plt.imshow(img)
plt.show()
print(pred_gender(img))

5. 今後の課題と判別結果

精度は上がっていったが、まだ画像サイズを大きくしたりなど精度が上がるかどうかみていかなければならない

成果物

成果物2


精度が7割とすごい良いものはできませんでしたが今後改善していくとすれば、ネットから集めるのではなく同じような角度や材料だけを写していくよにしなければならないのかと思います。また材料の劣化具合によっては違う材料と判別される可能性があるため同じ材料でも劣化具合の大きいものから小さいものまで幅広い写真を集めなければならないのが今後の課題になってきます。

成果物5

結果は屋根材の写真を入れた所、無事に材料と同じ材料名が返ってきました

アプリ

6. 出力結果に対する考察、今後の実用性


今回はただ材料の種類の判別のみとなっていますが、これを写真の集め方や撮り方などを統一し改善させていけば材料別の劣化具合を判別出来るようなものが出来てくるのではないかと思います。さほど実用性はないですが建築関係以外の方も塗装時期や葺き直し時期を判断出来るのではないかと思います。

今の段階での実用性はありませんが、建築の知識が乏しい一般の方を騙すような業者もいますので業者任せの判断ではなく自分の判断基準となるような判別器を今後作っていければなと考えています。

7. 最後に

木造住宅に関わる仕事の方も使う機会は少ないと思いますが、ご自宅の屋根の種類を知りたい場合など使ってみてください。

終わり


この記事が気に入ったらサポートをしてみませんか?