訂閱
糾錯
加入自媒體

如何設計可口可樂瓶的圖像識別方法?

介紹

可口可樂公司已經(jīng)進行了瓶子的再利用,接受了其隨之而來的所有環(huán)境影響和金錢利益。當客戶購買玻璃瓶中的可樂飲料時,他們會在返回空瓶時獲得獎勵,而如果沒有獎勵則會這些玻璃瓶被扔掉和浪費,所以我們可以設計一種自動識別可口可樂瓶的圖像識別方法。使用帶有大“ Coca Cola”字樣的標簽可以輕松辨認可口可樂瓶,而且該字樣通常為白色,我們可以通過隔離白色并在分割圖像上訓練模型來獲得標簽。依賴庫import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
from matplotlib import colors
import os
import cv2
import PIL
from tensorflow.keras.layers import Dense,Conv2D, Dropout,F(xiàn)latten, MaxPooling2D
from tensorflow import keras
from tensorflow.keras.models import Sequential, save_model, load_model
from tensorflow.keras.optimizers import Adam
import tensorflow as tf
from tensorflow.keras.preprocessing.image import img_to_array
from tensorflow.keras.preprocessing.image import load_img
from tensorflow.keras.a(chǎn)pplications.inception_v3 import InceptionV3, preprocess_input
from tensorflow.keras.callbacks import ModelCheckpoint
from sklearn.decomposition import PCA
Numpy用于操縱數(shù)組數(shù)據(jù)。Matplotlib用于可視化圖像,并顯示在特定的顏色范圍內顏色可辨性。OS用于訪問文件結構。CV2用于讀取圖像并將其轉換為不同的配色方案。Keras用于實際的神經(jīng)網(wǎng)絡。轉換顏色方案確定適當?shù)念伾桨福簽榱四軌蚋綦x顏色,我們需要檢查顏色在不同配色方案中的可分辨性,可以為此使用3D圖首先,我們可以在3D空間中以RGB顏色格式可視化圖像。在這里,我們基本上將圖像分為其成分(在這種情況下為紅色,綠色和藍色),然后設置3D圖;接下來是對圖像進行整形,然后對圖像進行歸一化,從而將范圍從0-255減小到0-1;最后,使用scatter()函數(shù)創(chuàng)建散點圖,然后我們相應地標記軸。red, green, blue = cv2.split(img)
fig = plt.figure()
axis = fig.a(chǎn)dd_subplot(1, 1, 1, projection="3d")
pixel_colors = img.reshape((np.shape(img)[0]*np.shape(img)[1], 3))
norm = colors.Normalize(vmin=-1.,vmax=1.)
norm.a(chǎn)utoscale(pixel_colors)
pixel_colors = norm(pixel_colors).tolist()
axis.scatter(red.flatten(), green.flatten(), blue.flatten(), facecolors=pixel_colors, marker=".")
axis.set_xlabel("Red")
axis.set_ylabel("Green")
axis.set_zlabel("Blue")
plt.show()

HSL和HSV方案通?梢愿玫赜糜趫D像分割,我們可以在HSL方案中繪制圖像的3D圖。hue, saturation, lightness = cv2.split(img)
fig = plt.figure()
axis = fig.a(chǎn)dd_subplot(1, 1, 1, projection="3d")
axis.scatter(hue.flatten(), saturation.flatten(), lightness.flatten(), facecolors=pixel_colors, marker=".")
axis.set_xlabel("Hue")
axis.set_ylabel("Saturation")
axis.set_zlabel("Lightness")
plt.show()

要注意的是,第二種圖中的特定顏色不像第一種中那樣混亂,我們可以很容易地從其余像素中分辨出白色像素。轉換顏色默認情況下,CV2以BGR方案讀取圖像。img = cv2.imread(img_path)
plt.imshow(img)
plt.show()

該圖像需要先轉換為RGB格式img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
plt.imshow(img)
plt.show()

最后,應將此圖像轉換為HLS方案,以便于識別顏色。HSL是圖像的色相,飽和度和亮度的描述。img = cv2.cvtColor(img, cv2.COLOR_RGB2HLS)
plt.imshow(img)
plt.show()

隔離色白色:我們?yōu)榘咨付ㄝ^低和較高的閾值,然后使用cv2.inRange()指定對HSL圖像進行閾值處理的蒙版,這會返回0和1。然后,我們使用bitwise_and函數(shù)將蒙版施加到原始RGB圖像上,如果蒙版的相應值為1,它將保留像素值,同時我們應用高斯模糊以平滑邊緣。hsl_img = cv2.cvtColor(img, cv2.COLOR_RGB2HLS)
low_threshold = np.a(chǎn)rray([0, 200, 0], dtype=np.uint8)
high_threshold = np.a(chǎn)rray([180, 255, 255], dtype=np.uint8)
mask = cv2.inRange(hsl_img, low_threshold, high_threshold)
white_parts = cv2.bitwise_and(img, img, mask = mask)
blur = cv2.GaussianBlur(white_parts, (7,7), 0)

INCEPTIONV3的遷移學習有些模型需要很長時間來訓練,但最終仍然沒有達到預計的預測精度。雖然從零開始創(chuàng)建模型沒問題,但遷移學習使用的模型在ImageNet圖像上產(chǎn)生了巨大的效果。在這個特定的項目中,我會展示如何使用InceptionV3。我們定義要使用的模型,包括權重和輸入形狀,然后將X的值放入模型中,并將結果值保存在名為“bottle_nec_features_train”的變量中。model = InceptionV3(weights='imagenet', include_top=False, input_shape=(299, 299, 3))
bottle_neck_features_train = model.predict_generator(X, n/32, verbose=1)
bottle_neck_features_train.shape
np.savez('inception_features_train', features=bottle_neck_features_train)
train_data = np.load('inception_features_train.npz')['features']
train_labels = np.a(chǎn)rray([0] * m + [1] * p) // where m+p = n

結果特征的形狀為((n,8,8,2048)),n為所用圖像的數(shù)量;然后,我們將值保存在名為“ inception_features_train.npz”的文件中,以避免重復的預訓練。可口可樂瓶識別是一個二進制分類問題(一個瓶子要么是可口可樂瓶,要么不是),因此,標簽可以是“可樂”的0或“非可樂”的1(或數(shù)字對的任何其他組合)?梢酝ㄟ^創(chuàng)建一系列等于可樂瓶圖像數(shù)量的零,然后為其余圖像添加一個零,來制作出訓練標簽。神經(jīng)網(wǎng)絡神經(jīng)網(wǎng)絡可以描述為一系列通過模仿人腦工作方式來解決問題的算法,在這里,我們采用序列Keras模型。classifier = Sequential()
classifier.a(chǎn)dd(Conv2D(32, (3, 3), activation='relu', input_shape=train_data.shape[1:], padding='same'))
classifier.a(chǎn)dd(Conv2D(32, (3, 3), activation='relu', padding='same'))
classifier.a(chǎn)dd(MaxPooling2D(pool_size=(3, 3)))
classifier.a(chǎn)dd(Dropout(0.25))
classifier.a(chǎn)dd(Conv2D(64, (3, 3), activation='relu', padding='same'))
classifier.a(chǎn)dd(Conv2D(64, (3, 3), activation='relu', padding='same'))
classifier.a(chǎn)dd(MaxPooling2D(pool_size=(2, 2)))
classifier.a(chǎn)dd(Dropout(0.50))
classifier.a(chǎn)dd(Flatten())
classifier.a(chǎn)dd(Dense(512, activation='relu'))
classifier.a(chǎn)dd(Dropout(0.6))
classifier.a(chǎn)dd(Dense(256, activation='relu'))
classifier.a(chǎn)dd(Dropout(0.5))
classifier.a(chǎn)dd(Dense(1, activation='sigmoid'))

輸入層是卷積層,用于該層的參數(shù)是:過濾器的數(shù)量為32,內核大小為3×3,激活函數(shù)為“整流線性單位”,輸入形狀為一幅圖像的形狀,并進行填充。第一個conv2d層的輸入總是4D數(shù)組,前三個維度是圖像輸入,最后一個維度是通道。校正后的線性單元是一個非線性激活函數(shù),盡管看起來是一個線性函數(shù),但它執(zhí)行的計算可能產(chǎn)生作為輸入的附加值,也可能產(chǎn)生零。MaxPooling用于特征提取,我們將池大小設置為3,3,這意味著模型將提取一個3,3像素圖像,并在該池中獲得最大值。dropout 用于防止過度擬合,在訓練階段的每次更新時,它會將隱藏單元的輸出邊緣隨機設置為0。Flatten層將輸入數(shù)據(jù)轉換為2D數(shù)組,全連接層確保一層的每個節(jié)點都連接到下一層的另一個節(jié)點。我們將Sigmoid激活函數(shù)用于輸出層。輸入將轉換為0.0到1.0之間的值,遠大于1.0的輸入將轉換為值1.0,類似地,遠小于0.0的值將捕捉為0.0。對于所有可能的輸入,函數(shù)的形狀為S形,范圍從零到0.5到1.0。為了以特定的間隔保存模型和權重,我們將ModelCheckpoint與model.fit一起使用。將'save_best_only'設置為true可確保僅保存產(chǎn)生最佳結果的模型,最后,我們編譯模型并擬合數(shù)據(jù)。checkpointer = ModelCheckpoint(filepath='./weights_inception.hdf5', verbose=1, save_best_only=True)
classifier.compile(optimizer='adam',loss='binary_crossentropy',metrics=['binary_accuracy'])
history = classifier.fit(train_data, train_labels,epochs=50,batch_size=32, validation_split=0.3,  verbose=2, callbacks=[checkpointer], shuffle=True)

執(zhí)行預測由于我們需要使用與輸入到分類器的數(shù)據(jù)相似的數(shù)據(jù),因此我們可以編寫一個函數(shù)來進行轉換然后進行預測。def predict(filepath):
   img = cv2.imread(filepath)
   img = cv2.resize(img,(299,299))
   img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
   hsl_img = cv2.cvtColor(img, cv2.COLOR_RGB2HLS)
   low_threshold = np.a(chǎn)rray([0, 200, 0], dtype=np.uint8)
   high_threshold = np.a(chǎn)rray([180, 255, 255], dtype=np.uint8)
   mask = cv2.inRange(hsl_img, low_threshold, high_threshold)
   white_parts = cv2.bitwise_and(img, img, mask = mask)
   blur = cv2.GaussianBlur(white_parts, (7,7), 0)
   print(img.shape)
   clf = InceptionV3(weights='imagenet', include_top=False, input_shape=white_parts.shape)
   bottle_neck_features_predict = clf.predict(np.a(chǎn)rray([white_parts]))[0]
   np.savez('inception_features_prediction', features=bottle_neck_features_predict)
   prediction_data = np.load('inception_features_prediction.npz')['features']
   q = model.predict( np.a(chǎn)rray( [prediction_data,] )  )
   prediction = q[0]
   prediction = int(prediction)
   print(prediction)

下一步在進行預測之前我們需要準備以下東西:有效的預測模型。保存的模型值。用于預測的圖像。準備進行預測的功能。現(xiàn)在,我們可以對圖像進行預測了。我們需要做的就是調用predict函數(shù)并將路徑傳遞給圖像作為參數(shù)。predict("./train/Coke Bottles/Coke1.png")

這應該提供1作為輸出,因為我們的可樂瓶圖像標記為1。保存模型如果這在軟件中完全適用,例如使用OpenCV模塊查看圖像或視頻并進行預測的實時應用程序,那么我們就不能期望每次打開程序時都訓練我們的模型。更為合理的做法是保存模型并在程序打開后將其加載,這意味著我們需要利用Keras的load_model和save_model,我們將其導入如下。from tensorflow.keras.models import Sequential, save_model, load_model

現(xiàn)在,我們可以通過調用save_model() 并輸入文件夾名稱作為參數(shù)來保存模型。save_model(save_model)

最后,我們可以簡單地使用 load_model 加載模型,而不用輸入代碼來重新訓練模型,從而整理所有程序。load_model("./save_model")


聲明: 本文由入駐維科號的作者撰寫,觀點僅代表作者本人,不代表OFweek立場。如有侵權或其他問題,請聯(lián)系舉報。

發(fā)表評論

0條評論,0人參與

請輸入評論內容...

請輸入評論/評論長度6~500個字

您提交的評論過于頻繁,請輸入驗證碼繼續(xù)

暫無評論

暫無評論

人工智能 獵頭職位 更多
掃碼關注公眾號
OFweek人工智能網(wǎng)
獲取更多精彩內容
文章糾錯
x
*文字標題:
*糾錯內容:
聯(lián)系郵箱:
*驗 證 碼:

粵公網(wǎng)安備 44030502002758號