Klasifikasi Gambar Menggunakan Model Pra-Terlatih

Dalam pelajaran ini, Anda akan belajar menggunakan model terlatih untuk mendeteksi objek dalam gambar tertentu. Anda akan menggunakansqueezenet modul terlatih yang mendeteksi dan mengklasifikasikan objek dalam gambar tertentu dengan sangat akurat.

Buka yang baru Juypter notebook dan ikuti langkah-langkah untuk mengembangkan aplikasi klasifikasi gambar ini.

Mengimpor Perpustakaan

Pertama, kami mengimpor paket yang diperlukan menggunakan kode di bawah ini -

from caffe2.proto import caffe2_pb2
from caffe2.python import core, workspace, models
import numpy as np
import skimage.io
import skimage.transform
from matplotlib import pyplot
import os
import urllib.request as urllib2
import operator

Selanjutnya, kami menyiapkan beberapa variables -

INPUT_IMAGE_SIZE = 227
mean = 128

Gambar yang digunakan untuk pelatihan jelas akan memiliki ukuran yang bervariasi. Semua gambar ini harus diubah menjadi ukuran tetap untuk pelatihan yang akurat. Demikian pula, gambar uji dan gambar yang ingin Anda prediksi di lingkungan produksi juga harus dikonversi ke ukurannya, sama dengan yang digunakan selama pelatihan. Jadi, kami membuat variabel di atas disebutINPUT_IMAGE_SIZE memiliki nilai 227. Karenanya, kami akan mengonversi semua gambar kami ke ukuran227x227 sebelum menggunakannya di classifier kami.

Kami juga mendeklarasikan variabel yang disebut mean memiliki nilai 128, yang nantinya digunakan untuk meningkatkan hasil klasifikasi.

Selanjutnya, kami akan mengembangkan dua fungsi untuk memproses gambar.

Pengolahan citra

Pemrosesan gambar terdiri dari dua langkah. Yang pertama adalah mengubah ukuran gambar, dan yang kedua adalah memotong gambar secara terpusat. Untuk kedua langkah ini, kami akan menulis dua fungsi untuk mengubah ukuran dan memotong.

Mengubah Ukuran Gambar

Pertama, kita akan menulis fungsi untuk mengubah ukuran gambar. Seperti yang dikatakan sebelumnya, kami akan mengubah ukuran gambar menjadi227x227. Jadi mari kita definisikan fungsinyaresize sebagai berikut -

def resize(img, input_height, input_width):

Kami mendapatkan rasio aspek gambar dengan membagi lebar dengan tinggi.

original_aspect = img.shape[1]/float(img.shape[0])

Jika rasio aspek lebih besar dari 1, ini menunjukkan bahwa gambar tersebut lebar, artinya dalam mode lanskap. Kami sekarang menyesuaikan tinggi gambar dan mengembalikan gambar yang diubah ukurannya menggunakan kode berikut -

if(original_aspect>1):
   new_height = int(original_aspect * input_height)
   return skimage.transform.resize(img, (input_width,
   new_height), mode='constant', anti_aliasing=True, anti_aliasing_sigma=None)

Jika rasio aspeknya less than 1, ini menunjukkan portrait mode. Kami sekarang menyesuaikan lebar menggunakan kode berikut -

if(original_aspect<1):
   new_width = int(input_width/original_aspect)
   return skimage.transform.resize(img, (new_width,
   input_height), mode='constant', anti_aliasing=True, anti_aliasing_sigma=None)

Jika rasio aspek sama 1, kami tidak melakukan penyesuaian tinggi / lebar.

if(original_aspect == 1):
   return skimage.transform.resize(img, (input_width,
   input_height), mode='constant', anti_aliasing=True, anti_aliasing_sigma=None)

Kode fungsi lengkap diberikan di bawah ini untuk referensi cepat Anda -

def resize(img, input_height, input_width):
   original_aspect = img.shape[1]/float(img.shape[0])
   if(original_aspect>1):
      new_height = int(original_aspect * input_height)
      return skimage.transform.resize(img, (input_width,
	   new_height), mode='constant', anti_aliasing=True, anti_aliasing_sigma=None)
   if(original_aspect<1):
         new_width = int(input_width/original_aspect)
         return skimage.transform.resize(img, (new_width,
         input_height), mode='constant', anti_aliasing=True, anti_aliasing_sigma=None)
   if(original_aspect == 1):
         return skimage.transform.resize(img, (input_width,
         input_height), mode='constant', anti_aliasing=True, anti_aliasing_sigma=None)

Kami sekarang akan menulis fungsi untuk memotong gambar di sekitar pusatnya.

Pemotongan Gambar

Kami mendeklarasikan crop_image berfungsi sebagai berikut -

def crop_image(img,cropx,cropy):

Kami mengekstrak dimensi gambar menggunakan pernyataan berikut -

y,x,c = img.shape

Kami membuat titik awal baru untuk gambar menggunakan dua baris kode berikut -

startx = x//2-(cropx//2)
starty = y//2-(cropy//2)

Akhirnya, kami mengembalikan gambar yang dipotong dengan membuat objek gambar dengan dimensi baru -

return img[starty:starty+cropy,startx:startx+cropx]

Seluruh kode fungsi diberikan di bawah ini untuk referensi cepat Anda -

def crop_image(img,cropx,cropy):
   y,x,c = img.shape
   startx = x//2-(cropx//2)
   starty = y//2-(cropy//2)
   return img[starty:starty+cropy,startx:startx+cropx]

Sekarang, kami akan menulis kode untuk menguji fungsi-fungsi ini.

Memproses Gambar

Pertama, salin file gambar ke images subfolder dalam direktori proyek Anda. tree.jpgfile disalin dalam proyek. Kode Python berikut memuat gambar dan menampilkannya di konsol -

img = skimage.img_as_float(skimage.io.imread("images/tree.jpg")).astype(np.float32)
print("Original Image Shape: " , img.shape)
pyplot.figure()
pyplot.imshow(img)
pyplot.title('Original image')

Outputnya adalah sebagai berikut -

Perhatikan bahwa ukuran gambar aslinya adalah 600 x 960. Kami perlu mengubah ukurannya menjadi spesifikasi kami227 x 227. Memanggil kami yang didefinisikan sebelumnyaresizefungsi melakukan pekerjaan ini.

img = resize(img, INPUT_IMAGE_SIZE, INPUT_IMAGE_SIZE)
print("Image Shape after resizing: " , img.shape)
pyplot.figure()
pyplot.imshow(img)
pyplot.title('Resized image')

Outputnya seperti yang diberikan di bawah ini -

Perhatikan bahwa sekarang ukuran gambar adalah 227 x 363. Kita perlu memotong ini227 x 227untuk umpan terakhir bagi algoritme kami. Kami memanggil fungsi tanaman yang telah ditentukan sebelumnya untuk tujuan ini.

img = crop_image(img, INPUT_IMAGE_SIZE, INPUT_IMAGE_SIZE)
print("Image Shape after cropping: " , img.shape)
pyplot.figure()
pyplot.imshow(img)
pyplot.title('Center Cropped')

Di bawah ini disebutkan adalah output dari kode -

Pada titik ini, gambar berukuran besar 227 x 227dan siap untuk diproses lebih lanjut. Kami sekarang menukar sumbu gambar untuk mengekstrak tiga warna menjadi tiga zona berbeda.

img = img.swapaxes(1, 2).swapaxes(0, 1)
print("CHW Image Shape: " , img.shape)

Diberikan di bawah ini adalah output -

CHW Image Shape: (3, 227, 227)

Perhatikan bahwa sumbu terakhir sekarang menjadi dimensi pertama dalam larik. Kami sekarang akan memplot tiga saluran menggunakan kode berikut -

pyplot.figure()
for i in range(3):
   pyplot.subplot(1, 3, i+1)
   pyplot.imshow(img[i])
   pyplot.axis('off')
   pyplot.title('RGB channel %d' % (i+1))

Outputnya dinyatakan di bawah ini -

Akhirnya, kami melakukan beberapa pemrosesan tambahan pada gambar seperti mengonversi Red Green Blue untuk Blue Green Red (RGB to BGR), menghapus mean untuk hasil yang lebih baik dan menambahkan sumbu ukuran batch menggunakan tiga baris kode berikut -

# convert RGB --> BGR
img = img[(2, 1, 0), :, :]
# remove mean
img = img * 255 - mean
# add batch size axis
img = img[np.newaxis, :, :, :].astype(np.float32)

Pada titik ini, gambar Anda sudah masuk NCHW formatdan siap untuk dimasukkan ke dalam jaringan kami. Selanjutnya, kami akan memuat file model terlatih kami dan memasukkan gambar di atas ke dalamnya untuk prediksi.

Memprediksi Objek dalam Gambar Olahan

Kami pertama-tama menyiapkan jalur untuk file init dan predict jaringan yang ditentukan dalam model Caffe terlatih.

Mengatur Jalur File Model

Ingat dari diskusi kita sebelumnya, semua model terlatih dipasang di modelsmap. Kami mengatur jalur ke folder ini sebagai berikut -

CAFFE_MODELS = os.path.expanduser("/anaconda3/lib/python3.7/site-packages/caffe2/python/models")

Kami menyiapkan jalur ke init_net protobuf dari file squeezenet model sebagai berikut -

INIT_NET = os.path.join(CAFFE_MODELS, 'squeezenet', 'init_net.pb')

Demikian juga, kami menyiapkan jalur ke predict_net protobuf sebagai berikut -

PREDICT_NET = os.path.join(CAFFE_MODELS, 'squeezenet', 'predict_net.pb')

Kami mencetak dua jalur untuk tujuan diagnosis -

print(INIT_NET)
print(PREDICT_NET)

Kode di atas bersama dengan hasilnya diberikan di sini untuk referensi cepat Anda -

CAFFE_MODELS = os.path.expanduser("/anaconda3/lib/python3.7/site-packages/caffe2/python/models")
INIT_NET = os.path.join(CAFFE_MODELS, 'squeezenet', 'init_net.pb')
PREDICT_NET = os.path.join(CAFFE_MODELS, 'squeezenet', 'predict_net.pb')
print(INIT_NET)
print(PREDICT_NET)

Outputnya disebutkan di bawah ini -

/anaconda3/lib/python3.7/site-packages/caffe2/python/models/squeezenet/init_net.pb
/anaconda3/lib/python3.7/site-packages/caffe2/python/models/squeezenet/predict_net.pb

Selanjutnya, kami akan membuat prediktor.

Membuat Predictor

Kami membaca file model menggunakan dua pernyataan berikut -

with open(INIT_NET, "rb") as f:
   init_net = f.read()
with open(PREDICT_NET, "rb") as f:
   predict_net = f.read()

Prediktor dibuat dengan meneruskan pointer ke dua file sebagai parameter ke Predictor fungsi.

p = workspace.Predictor(init_net, predict_net)

Itu pobjek adalah prediktor, yang digunakan untuk memprediksi objek dalam gambar tertentu. Perhatikan bahwa setiap gambar masukan harus dalam format NCHW seperti yang telah kita lakukan sebelumnyatree.jpg mengajukan.

Memprediksi Objek

Untuk memprediksi objek dalam gambar tertentu itu sepele - hanya menjalankan satu baris perintah. Kami memanggilrun metode di predictor objek untuk deteksi objek dalam gambar tertentu.

results = p.run({'data': img})

Hasil prediksi sekarang tersedia di results objek, yang kami ubah menjadi larik agar mudah dibaca.

results = np.asarray(results)

Cetak dimensi larik untuk pemahaman Anda menggunakan pernyataan berikut -

print("results shape: ", results.shape)

Outputnya seperti yang ditunjukkan di bawah ini -

results shape: (1, 1, 1000, 1, 1)

Kami sekarang akan menghapus sumbu yang tidak perlu -

preds = np.squeeze(results)

Predikasi teratas sekarang dapat diambil dengan mengambil max nilai dalam preds Himpunan.

curr_pred, curr_conf = max(enumerate(preds), key=operator.itemgetter(1))
print("Prediction: ", curr_pred)
print("Confidence: ", curr_conf)

Outputnya adalah sebagai berikut -

Prediction: 984
Confidence: 0.89235985

Seperti yang Anda lihat, model telah memprediksi objek dengan nilai indeks 984 dengan 89%kepercayaan. Indeks 984 tidak terlalu masuk akal bagi kami dalam memahami jenis objek yang terdeteksi. Kita perlu mendapatkan nama yang dirangkai untuk objek tersebut menggunakan nilai indeksnya. Jenis objek yang dikenali model beserta nilai indeksnya yang sesuai tersedia di repositori github.

Sekarang, kita akan melihat bagaimana mengambil nama untuk objek kita yang memiliki nilai indeks 984.

Hasil Merangkai

Kami membuat objek URL ke repositori github sebagai berikut -

codes = "https://gist.githubusercontent.com/aaronmarkham/cd3a6b6ac0
71eca6f7b4a6e40e6038aa/raw/9edb4038a37da6b5a44c3b5bc52e448ff09bfe5b/alexnet_codes"

Kami membaca konten URL -

response = urllib2.urlopen(codes)

Tanggapan akan berisi daftar semua kode dan deskripsinya. Beberapa baris tanggapan ditampilkan di bawah ini untuk pemahaman Anda tentang isinya -

5: 'electric ray, crampfish, numbfish, torpedo',
6: 'stingray',
7: 'cock',
8: 'hen',
9: 'ostrich, Struthio camelus',
10: 'brambling, Fringilla montifringilla',

Kami sekarang mengulangi seluruh larik untuk menemukan kode yang kami inginkan dari 984 menggunakan file for loop sebagai berikut -

for line in response:
   mystring = line.decode('ascii')
   code, result = mystring.partition(":")[::2]
   code = code.strip()
   result = result.replace("'", "")
   if (code == str(curr_pred)):
      name = result.split(",")[0][1:]
      print("Model predicts", name, "with", curr_conf, "confidence")

Saat Anda menjalankan kode, Anda akan melihat output berikut -

Model predicts rapeseed with 0.89235985 confidence

Sekarang Anda dapat mencoba model pada gambar lain.

Memprediksi Gambar yang Berbeda

Untuk memprediksi gambar lain, cukup salin file gambar ke dalam imagesfolder dari direktori proyek Anda. Ini adalah direktori tempat kami sebelumnyatree.jpgfile disimpan. Ubah nama file gambar di kode. Hanya satu perubahan yang diperlukan seperti yang ditunjukkan di bawah ini

img = skimage.img_as_float(skimage.io.imread("images/pretzel.jpg")).astype(np.float32)

Gambar asli dan hasil prediksi ditunjukkan di bawah ini -

Outputnya disebutkan di bawah ini -

Model predicts pretzel with 0.99999976 confidence

Seperti yang Anda lihat, model terlatih mampu mendeteksi objek dalam gambar tertentu dengan sangat akurat.

Sumber Penuh

Sumber lengkap kode di atas yang menggunakan model terlatih untuk deteksi objek dalam gambar tertentu disebutkan di sini untuk referensi cepat Anda -

def crop_image(img,cropx,cropy):
   y,x,c = img.shape
   startx = x//2-(cropx//2)
   starty = y//2-(cropy//2)
   return img[starty:starty+cropy,startx:startx+cropx]
img = skimage.img_as_float(skimage.io.imread("images/pretzel.jpg")).astype(np.float32)
print("Original Image Shape: " , img.shape)
pyplot.figure()
pyplot.imshow(img)
pyplot.title('Original image')
img = resize(img, INPUT_IMAGE_SIZE, INPUT_IMAGE_SIZE)
print("Image Shape after resizing: " , img.shape)
pyplot.figure()
pyplot.imshow(img)
pyplot.title('Resized image')
img = crop_image(img, INPUT_IMAGE_SIZE, INPUT_IMAGE_SIZE)
print("Image Shape after cropping: " , img.shape)
pyplot.figure()
pyplot.imshow(img)
pyplot.title('Center Cropped')
img = img.swapaxes(1, 2).swapaxes(0, 1)
print("CHW Image Shape: " , img.shape)
pyplot.figure()
for i in range(3):
pyplot.subplot(1, 3, i+1)
pyplot.imshow(img[i])
pyplot.axis('off')
pyplot.title('RGB channel %d' % (i+1))
# convert RGB --> BGR
img = img[(2, 1, 0), :, :]
# remove mean
img = img * 255 - mean
# add batch size axis
img = img[np.newaxis, :, :, :].astype(np.float32)
CAFFE_MODELS = os.path.expanduser("/anaconda3/lib/python3.7/site-packages/caffe2/python/models")
INIT_NET = os.path.join(CAFFE_MODELS, 'squeezenet', 'init_net.pb')
PREDICT_NET = os.path.join(CAFFE_MODELS, 'squeezenet', 'predict_net.pb')
print(INIT_NET)
print(PREDICT_NET)
with open(INIT_NET, "rb") as f:
   init_net = f.read()
with open(PREDICT_NET, "rb") as f:
   predict_net = f.read()
p = workspace.Predictor(init_net, predict_net)
results = p.run({'data': img})
results = np.asarray(results)
print("results shape: ", results.shape)
preds = np.squeeze(results)
curr_pred, curr_conf = max(enumerate(preds), key=operator.itemgetter(1))
print("Prediction: ", curr_pred)
print("Confidence: ", curr_conf)
codes = "https://gist.githubusercontent.com/aaronmarkham/cd3a6b6ac071eca6f7b4a6e40e6038aa/raw/9edb4038a37da6b5a44c3b5bc52e448ff09bfe5b/alexnet_codes"
response = urllib2.urlopen(codes)
for line in response:
   mystring = line.decode('ascii')
   code, result = mystring.partition(":")[::2]
   code = code.strip()
   result = result.replace("'", "")
   if (code == str(curr_pred)):
      name = result.split(",")[0][1:]
      print("Model predicts", name, "with", curr_conf, "confidence")

Saat ini, Anda sudah tahu cara menggunakan model terlatih untuk melakukan prediksi pada kumpulan data Anda.

Selanjutnya adalah mempelajari cara mendefinisikan file neural network (NN) arsitektur di Caffe2dan latih mereka di kumpulan data Anda. Sekarang kita akan belajar cara membuat NN layer tunggal yang sepele.