使用深度学习Web项目的手写Marathi印地语字母书写和检测
For the sake of convenience and clarity, This article is divided into two parts as follows :
為了方便和清楚起見,本文分為以下兩個部分:
A. In the first part, we are gonna understand how to build a neural net on Kaggle (Since our data is Huge we are using an online notebook).
答:在第一部分中,我們將了解如何在Kaggle上構(gòu)建神經(jīng)網(wǎng)絡(luò)(由于我們的數(shù)據(jù)非常龐大,我們正在使用在線筆記本)。
B. In the second part, We are building a clean and simple web app using flask so that the user can draw the character on board and our model predicts it
B.在第二部分中,我們將使用flask構(gòu)建一個干凈而簡單的Web應(yīng)用程序,以便用戶可以在板上繪制字符,并且我們的模型可以預(yù)測該字符
Final Output will look like
最終輸出看起來像
A.建立卷積神經(jīng)網(wǎng)絡(luò)模型,對其進(jìn)行訓(xùn)練并導(dǎo)出模型 (A. Building Convolutional Neural Net Model, Train it and Export the Model)
Final Convolutional Model Structure ( Layer & IP/OP wise )最終卷積模型結(jié)構(gòu)(明智的分層和IP / OP)The dataset is available on Kaggle here. You can either download the dataset or you can just go to Kaggle and create a new notebook there. As the second option is easy and convenient it’s suitable for most of us.
該數(shù)據(jù)集可在此處的Kaggle上找到。 您可以下載數(shù)據(jù)集,也可以直接轉(zhuǎn)到Kaggle在此處創(chuàng)建一個新的筆記本。 由于第二種選擇既方便又方便,因此適合我們大多數(shù)人。
The very first thing about building any machine learning or deep learning project is to have clean data to have better outputs but fortunately and to keep it simple we already have much cleaner data.
構(gòu)建任何機器學(xué)習(xí)或深度學(xué)習(xí)項目的第一件事是擁有干凈的數(shù)據(jù)以提供更好的輸出,但是幸運的是,為了保持簡單,我們已經(jīng)擁有了更干凈的數(shù)據(jù)。
We start the tutorial by including the libraries needed for the model building and other stuff
我們通過包括模型構(gòu)建所需的庫和其他內(nèi)容開始教程
import pandas as pd import numpy as npfrom keras.models import Sequential from keras.layers import Dense from keras.layers import Dropout from keras.layers import Flatten from keras.callbacks import EarlyStopping from keras.layers.convolutional import Conv2D from keras.layers.convolutional import MaxPooling2D from keras.utils import np_utilsPandas is used to handle huge data frames in the most efficient way possible Numpy is used to do numerical calculations and data type conversions and Keras is a deep learning library popularly used to build different deep learning models
Pandas用于以盡可能高效的方式處理海量數(shù)據(jù)幀Numpy用于進(jìn)行數(shù)值計算和數(shù)據(jù)類型轉(zhuǎn)換,而Keras是深度學(xué)習(xí)庫,通常用于構(gòu)建不同的深度學(xué)習(xí)模型
df = pd.read_csv('/kaggle/input/devanagari-character-set/data.csv')# From First Col to (last-1) col with all rows X = df.iloc[:,:-1]# last Col with all rows y = df.iloc[:,-1]Now we load the actual data in the pandas’ data frame as a table-like format. Our data frame has 1025 columns as (32 x 32) pixel columns and the last column for that actual character string. we split data into input and output parameter as first 1024 columns as input X and last column as output y
現(xiàn)在,我們以表格形式將實際數(shù)據(jù)加載到熊貓的數(shù)據(jù)框中。 我們的數(shù)據(jù)框有1025列(32 x 32)像素列,最后一列是該實際字符串。 我們將數(shù)據(jù)分為輸入和輸出參數(shù),前1024列作為輸入X,最后一列作為輸出y
Labelbinarizer: Binarize labels in a one-vs-all fashion
Labelbinarizer:以一對多的方式對標(biāo)簽進(jìn)行二值化
Labelbinarizer: indexes the output column of data frame i.e y and store it into an array which can be accessed through .classes_ param of an object
Labelbinarizer:索引數(shù)據(jù)幀的輸出列,即y并將其存儲到一個數(shù)組中,該數(shù)組可以通過對象的.classes_ param訪問
# output in binary format for NN from sklearn.preprocessing import LabelBinarizer binencoder = LabelBinarizer() y = binencoder.fit_transform(y)We had given data in tabular format as it is pixel data but to see how the actual image looks like we reshape the data using NumPy reshape to image like a 2D array of pixels and plot it using matplotlib’s pyplot. I used that imshow function to display the very first image in IMG array but you can view any image just by changing index of the array
我們已經(jīng)以表格格式給出了數(shù)據(jù),因為它是像素數(shù)據(jù),但是要查看實際圖像的樣子,我們使用NumPy整形來對數(shù)據(jù)進(jìn)行整形以像像素的2D數(shù)組那樣成像,并使用matplotlib的pyplot對其進(jìn)行繪制。 我使用了imshow函數(shù)來顯示IMG數(shù)組中的第一張圖像,但是您只需更改數(shù)組的索引就可以查看任何圖像
X_images = X.values.reshape(92000,32,32) import matplotlib.pyplot as plt plt.imshow(X_images[0]) plt.show()train_test_split : Split arrays or matrices into random train and test subsets
train_test_split:將數(shù)組或矩陣拆分為隨機的訓(xùn)練和測試子集
now for testing and training the model we have split the data frame horizontally like some rows for training and other for testing sci-kit learns train_test_split function help to split the data frame as per ratio given (test_size = 0.2 in our case which is 20% test data 80% training data)
現(xiàn)在,為了測試和訓(xùn)練模型,我們已經(jīng)像一些行進(jìn)行訓(xùn)練一樣對數(shù)據(jù)幀進(jìn)行了水平分割,而其他一些用于測試sci-kit的東西則學(xué)習(xí)了train_test_split函數(shù),它有助于按照給定的比率來分割數(shù)據(jù)幀(在本例中,test_size = 0.2,即20%測試數(shù)據(jù)80%的培訓(xùn)數(shù)據(jù))
after splitting we divide each value in the training set and testing set’s input by 255 as the color value ranges in 0 to 255 and for neuron value range should be 0.0 to 1.0
分割后,我們將訓(xùn)練集和測試集輸入中的每個值除以255,因為顏色值范圍在0到255之間,而神經(jīng)元值范圍應(yīng)該在0.0到1.0之間
from sklearn.model_selection import train_test_split X_train, X_test, y_train, y_test = train_test_split(X_images, y, test_size=0.20, random_state=92)X_train = X_train/255 X_test = X_test/255# changing from 3 to 4 dimensions of inputss X_train = X_train.reshape(X_train.shape[0], 32, 32, 1).astype('float32') X_test = X_test.reshape(X_test.shape[0], 32, 32, 1).astype('float32')also, we need to shift our data from 3D to 4D because our neural net input itself adds one layer of the array and need to change the datatype to float using Numpy
同樣,我們需要將數(shù)據(jù)從3D轉(zhuǎn)換為4D,因為神經(jīng)網(wǎng)絡(luò)輸入本身會增加數(shù)組的一層,并且需要使用Numpy將數(shù)據(jù)類型更改為float
我們的目標(biāo)是首先構(gòu)建卷積模型,然后在卷積模型的輸出上構(gòu)建密集網(wǎng)絡(luò)以唯一地標(biāo)識46個字符,因此讓我們深入了解 (Our target is to build the convolutional model first the on the output of the convolutional model we build the dense network as to uniquely identifying 46 characters so let dive into that)
# Building the Convolutional Model conv_model = Sequential()# Adding first CONV layer wit max-pooling conv_model.add(Conv2D(32, (4, 4), input_shape=(32, 32,1),activation='relu', name="firstConv") )conv_model.add(MaxPooling2D(pool_size=(2, 2), name="FirstPool") )# Adding second set of Conv and max-pool layersconv_model.add(Conv2D(64, (3, 3), activation='relu', name="SecondConv") )conv_model.add(MaxPooling2D(pool_size=(2, 2),name="SecondPool") )conv_model.add(Dropout(0.2)) # Prevents Overfitting in Conv NeteSo started with sequential we add first conv2D layer of 32 filters and relu activation (the name is just for model.summary() purpose) after each convolution layer we add max polling which is basically selecting the max value form the given square window of an array
因此,從順序開始,我們在32個濾鏡上添加了第一個conv2D層,并在每個卷積層之后添加了relu激活(名稱僅用于model.summary()目的),我們添加了max polling,這基本上是從給定的正方形窗口中選擇最大值。數(shù)組
similarly, we added a 2nd Conv layer we add 64 filters with feature map kernel size of 3 x 3 and again we do max-pooling of 2 x 2 window
同樣,我們添加了第二個Conv層,添加了64個濾鏡,其特征圖內(nèi)核大小為3 x 3,并且再次進(jìn)行了2 x 2窗口的最大池化
After this two convolutional layer and pooling layers followed by them we need to add the dropout layer, there is the reason for that as we train our convolutional after some training it starts overfitting crazily to stop that after tuning all the major hyperparameters we have to tune for drop out rate in our case 20% dropout worked fine
在這兩個卷積層和池化層之后, 我們需要添加退出層,這是因為在進(jìn)行一些訓(xùn)練后訓(xùn)練卷積時,它開始瘋狂地過度擬合,從而在調(diào)整了所有需要調(diào)整的主要超參數(shù)之后停止了過度擬合在我們的案例中,輟學(xué)率是20%
# Building Dense neural net on outputs of the Conv Net# Input Layer : Flattening the Outputs of the Conv Nets conv_model.add(Flatten())# Two Dense Layers 128 Neuraons and 50 Neurons conv_model.add(Dense(128,activation='relu',name="dense_1") ) conv_model.add(Dense(50, activation='relu', name="dense_2") )# Output Layer with 46 Unique Outputs conv_model.add(Dense(46, activation='softmax', name="modeloutput") )conv_model.compile(loss='categorical_crossentropy', optimizer='adam',metrics=['accuracy'] )On the output of the conv net, we first flatten it to 1D and start building fully connected dense net of 128, 50, 48 layers respectively with first 2 rely activation and of course last needs to be different as softmax activation we compile the modal using categorical cross-entropy as we have multiple choices at the output and optimizing it for accuracy
在conv net的輸出上,我們首先將其展平為1D并開始分別使用前2個依賴激活分別構(gòu)建128、50、48層的完全連接的密集網(wǎng)絡(luò),當(dāng)然最后一個需要不同,因為softmax激活我們使用以下方式編譯模態(tài)類別交叉熵,因為我們在輸出端有多種選擇,并對其進(jìn)行了優(yōu)化以提高準(zhǔn)確性
conv_model.summary() """ Model: "sequential_20" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= firstConv (Conv2D) (None, 29, 29, 32) 544 _________________________________________________________________ FirstPool (MaxPooling2D) (None, 14, 14, 32) 0 _________________________________________________________________ SecondConv (Conv2D) (None, 12, 12, 64) 18496 _________________________________________________________________ SecondPool (MaxPooling2D) (None, 6, 6, 64) 0 _________________________________________________________________ dropout_10 (Dropout) (None, 6, 6, 64) 0 _________________________________________________________________ flatten_16 (Flatten) (None, 2304) 0 _________________________________________________________________ dense_1 (Dense) (None, 128) 295040 _________________________________________________________________ dense_2 (Dense) (None, 50) 6450 _________________________________________________________________ modeloutput (Dense) (None, 46) 2346 ================================================================= Total params: 322,876 Trainable params: 322,876 Non-trainable params: 0 _________________________________________________________________ """Now is time to reflect before we start training the model layer and the trainable parameter in each layer
現(xiàn)在是時候開始思考,在我們開始訓(xùn)練模型層和每層中的可訓(xùn)練參數(shù)之前
this is the heart of this code as a lot of fitting the model on data gives the idea of how optimized it is for accuracy as well as all the other factors Ideally with every epoch your loss will be decreasing and accuracy is increasing
這是此代碼的核心,因為大量將模型擬合到數(shù)據(jù)上可得出如何針對準(zhǔn)確性以及所有其他因素進(jìn)行優(yōu)化的想法。 理想情況下,隨著時間的流逝,您的損失會減少,準(zhǔn)確性會增加
# Training the Model on TRaining Dataset result = conv_model.fit(X_train, y_train, validation_split=0.20, epochs=10, batch_size=92,verbose=2) """ Train on 58880 samples, validate on 14720 samples Epoch 1/10- 37s - loss: 1.0177 - accuracy: 0.7208 - val_loss: 0.3405 - val_accuracy: 0.9010 Epoch 2/10- 36s - loss: 0.2779 - accuracy: 0.9165 - val_loss: 0.2022 - val_accuracy: 0.9397 Epoch 3/10- 36s - loss: 0.1771 - accuracy: 0.9452 - val_loss: 0.1631 - val_accuracy: 0.9521 Epoch 4/10- 36s - loss: 0.1273 - accuracy: 0.9600 - val_loss: 0.1546 - val_accuracy: 0.9542 Epoch 5/10- 37s - loss: 0.0975 - accuracy: 0.9692 - val_loss: 0.1290 - val_accuracy: 0.9634 Epoch 6/10- 37s - loss: 0.0787 - accuracy: 0.9751 - val_loss: 0.1255 - val_accuracy: 0.9637 Epoch 7/10- 36s - loss: 0.0676 - accuracy: 0.9781 - val_loss: 0.1206 - val_accuracy: 0.9668 Epoch 8/10- 36s - loss: 0.0567 - accuracy: 0.9806 - val_loss: 0.1007 - val_accuracy: 0.9717 Epoch 9/10- 36s - loss: 0.0475 - accuracy: 0.9845 - val_loss: 0.1057 - val_accuracy: 0.9698 Epoch 10/10- 37s - loss: 0.0452 - accuracy: 0.9850 - val_loss: 0.1075 - val_accuracy: 0.9707"""Now try the model on testing data to get testing accuracy and export the model to use it further in web app building You can also use pickle or joblib to export the model
現(xiàn)在嘗試對測試數(shù)據(jù)進(jìn)行建模以獲得測試準(zhǔn)確性,并導(dǎo)出模型以在Web應(yīng)用程序構(gòu)建中進(jìn)一步使用它。您還可以使用pickle或joblib導(dǎo)出模型
# TESt Data Testign Accuracy scores = conv_model.evaluate(X_test, y_test, verbose=0) print("Accuracy: %.2f%%" % (scores[1]*100))conv_model.save('/kaggle/working/conv_model.hdf5')This is Just for Fun piece of code this basically first how the image predict the output of the image by our model and display it below as you can change the num variable image will be changed
這只是一段有趣的代碼,基本上這首先是圖像如何通過我們的模型預(yù)測圖像的輸出并在下面顯示,因為您可以更改num變量圖像。
num = 25220 plt.imshow(X_images[num]) plt.show()imgTrans = X_images[num].reshape(1,32,32,1) imgTrans.shapepredictions = conv_model.predict(imgTrans) binencoder.classes_[np.argmax(predictions)]Congratulations You just completed the first part of this 2 part article!
恭喜,您剛剛完成了這兩部分文章的第一部分!
In this first part we
在第一部分中,我們
- Cleaned the Data 清理數(shù)據(jù)
- Built Convolutional Net 內(nèi)置卷積網(wǎng)
- Built Dense neural net on the back of conv net 在卷積網(wǎng)的背面建立密集的神經(jīng)網(wǎng)
- export the model 導(dǎo)出模型
B.圍繞卷積模型和“繪圖畫布”構(gòu)建Full Flask Flesh Web應(yīng)用程序。 (B. Building Full Flask Flesh web app around the convolutional model and Drawing Canvas.)
Now you have that model.hdf5 file.Congratulations on that! In this tutorial, we are using flask backend and bootstrap for a little styling. As both are Quick and Easy to learn technologies and super perfect for small-sized projects. To keep this article short and sweet I focused majorly on the core logic of the code and not the very minute details of UI and other stuff
現(xiàn)在您有了那個model.hdf5文件。恭喜! 在本教程中,我們將使用flask后端和bootstrap進(jìn)行一些樣式設(shè)置。 兩者都是快速且易于學(xué)習(xí)的技術(shù),對于小型項目而言非常完美。 為使本文簡短而有趣,我主要關(guān)注代碼的核心邏輯,而不是UI和其他內(nèi)容的詳細(xì)信息。
Starting with the Backend part flask app has only one starting file i.e app.py we make folders named static for all CSS and JS code templates for the front end HTML templates and one folder for our saved model file
從后端零件瓶應(yīng)用程序開始,只有一個開始文件,即app.py,我們?yōu)榍岸薍TML模板的所有CSS和JS代碼模板創(chuàng)建名為static的文件夾,為我們保存的模型文件創(chuàng)建一個文件夾
import pickle import cv2 from keras.models import load_model import tensorflow as tf import numpy as np from labels import labelsimport warningsmodel = load_model('kaggle-ip/conv_model_Final.hdf5', compile=False) graph = tf.get_default_graph()""" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= firstConv (Conv2D) (None, 29, 29, 32) 544 _________________________________________________________________ FirstPool (MaxPooling2D) (None, 14, 14, 32) 0 _________________________________________________________________ SecondConv (Conv2D) (None, 12, 12, 64) 18496 _________________________________________________________________ SecondPool (MaxPooling2D) (None, 6, 6, 64) 0 _________________________________________________________________ dropout_2 (Dropout) (None, 6, 6, 64) 0 _________________________________________________________________ flatten_2 (Flatten) (None, 2304) 0 _________________________________________________________________ dense_1 (Dense) (None, 128) 295040 _________________________________________________________________ dense_2 (Dense) (None, 50) 6450 _________________________________________________________________ modeloutput (Dense) (None, 46) 2346 ================================================================= Total params: 322,876 Trainable params: 322,876 Non-trainable params: 0 _________________________________________________________________ """def prepareImg(number):img = cv2.imread(f'uploads/image-{number}.png')img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)img = cv2.resize(img, (32, 32))img = img.reshape(1, 32, 32, 1)print(img.shape)return img# model.summary() # BE = pickle.load(open('kaggle-ip/labelBinarizerFinal.pickle', 'rb'))def GetPredict(x):with graph.as_default():pred = model.predict(prepareImg(x))warnings.simplefilter("ignore")index = np.argmax(pred)# index -= 1print(labels[index])return labels[index]#chr = BE.classes_[index]# print(chr)# GetPredict(41)""" Running Script : python -W ignore conv_model.py """First of all, we load the modal using Keras load_model method there are 2 functions in the code
首先,我們使用Keras load_model方法加載模態(tài),代碼中有2個函數(shù)
prepareImg: (prepareImg:)
- this function loads the uploaded image 此功能加載上傳的圖像
- convert it into Grayscale image 將其轉(zhuǎn)換為灰度圖像
- convert that grayscale into a 4D array of shape (1, 32, 32, 1) 將該灰度轉(zhuǎn)換為形狀為(1、32、32、1)的4D數(shù)組
- returns this 4D array 返回此4D數(shù)組
GetPredict: (GetPredict:)
This function takes imageId x as the parameter
此函數(shù)將imageId x作為參數(shù)
- load the image in Neural Net using prepareImg function 使用prepareImg函數(shù)將圖像加載到神經(jīng)網(wǎng)絡(luò)中
- find the maximum probability of 46 unique outputs 找到46個唯一輸出的最大概率
- returns the index of maximum probability 返回最大概率的索引
labels.py simply used export the actual value to the key index returned by Neural Net there are 46 values each can be accessed by a unique index
labels.py簡單地用于將實際值導(dǎo)出到Neural Net返回的鍵索引中,每個唯一索引可以訪問46個值
from flask import Flask, render_template, request, flash, redirect, jsonify, send_file import os from binascii import a2b_base64 import random import numpy as np from conv_model import GetPredict#BE = pickle.load(open('kaggle-ip/labelBinarizerFinal.pickle', 'rb'))app = Flask(__name__)# model = load_model('kaggle-ip/conv_model_Final.hdf5', compile=False) # graph1 = tf.get_default_graph() # K.clear_session()# Open it with Numpy Reshape it # Start the Model # Feed this Input Image # Get Result Return Request@app.route('/ref') def ref():return render_template('ref.html')@app.route('/upload', methods=['POST']) def uploadAndPredict():image_b64 = request.values['imageBase64']count = random.randint(0, 10000)# Removing Prefix from Data URIdata = image_b64.replace("data:image/png;base64,", '')binary_data = a2b_base64(data)# Get the Images Saved in Upload Folderfd = open(f'uploads/image-{count}.png', 'wb')fd.write(binary_data)fd.close()# Getting Prediction from Conv-modelchrX = GetPredict(count)# Sending the JSON response of the Objectres = {"imageID": count,"prediction": chrX}return jsonify(res)# Function to send image according to Id@app.route('/image/<imageID>') def getImage(imageID):filename = f'uploads/image-{imageID}.png'return send_file(filename, mimetype='image/png')@app.route('/') def home():return render_template('home.html')App.py is the root entry in the flask app it has multiple routes and associated functions to that routes as below
App.py是flask應(yīng)用程序中的根條目,它具有多個路由以及與該路由相關(guān)的功能,如下所示
“/ref”: this route sends to Ref Static page just show up a page
“ / ref ”:此路由發(fā)送到“ Ref Static”頁面,僅顯示一個頁面
“/upload”: there is a lot going in here
“ / upload ”:這里有很多內(nèi)容
- Image data URI is sent to the server 圖像數(shù)據(jù)URI被發(fā)送到服務(wù)器
- It is converted to PNG image and is saved in file system /uploads folder 它將轉(zhuǎn)換為PNG圖像,并保存在文件系統(tǒng)/ uploads文件夾中
- Image is feed to Neural Net and Output is taken 圖像被饋送到神經(jīng)網(wǎng)絡(luò)并獲取輸出
- Output and Random Id generated is sent to frontend in JSON format 生成的輸出和隨機ID以JSON格式發(fā)送到前端
3.”/image/<imageID>”: this route return the Image file of the Image ID passed as a parameter
3.” / image / <imageID> ”:此路由返回作為參數(shù)傳遞的Image ID的Image文件
4.”/” This is Homepage as renders Drawing screen on “Home.html”
4.” / ”這是主頁,“ Home.html”上的“繪圖”屏幕
Now we go by starting the very static part (just for show part) i.e ref.html
現(xiàn)在我們開始非常靜態(tài)的部分(僅用于顯示部分),即ref.html
<!DOCTYPE html> <html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>References - Marathi letter recognition | DL Project</title><linkrel="stylesheet"href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css"/><link rel="stylesheet" href="static/drawing-board/drawingboard.min.css" /><link rel="stylesheet" href="static/css/comman.css" /></head><body><!-- Header Code --><nav class="navbar navbar-light bg-primary"><a class="d-flex navbar-brand" href="#"><imgsrc="static/img/logo.png"width="50"height="50"class="d-inline-block align-top"alt=""style="border-radius: 50%;"/><h3 class="text-light px-2">Marathi Handwritten Letter Recognition</h3></a><div class="text-right"><a href="/" class="text-light"><button class="btn btn-light">Homepage</button></a></div></nav><!-- Body araa --><div class="container py-2"><h4>Marathi</h4><p>Marathi is an Indo-Aryan language spoken by about 71 million peoplemainly in the Indian state of Maharashtra and neighbouring states.Marathi is also spoken in Israel and Mauritius. Marathi is thought to bea descendent of Maharashtri, one of the Prakrit languages whichdeveloped from Sanskrit. <br />Marathi first appeared in writing duringthe 11th century in the form of inscriptions on stones and copperplates. From the 13th century until the mid 20th century, it was writtenwith the Modi alphabet. Since 1950 it has been written with theDevanāgarī alphabet.</p><hr class="my-3" /><h6>Marathi Vowels</h6><img src="static/img/ref/vowels.gif" alt="" class="w-100" /><hr class="my-3" /><h6>Marathi Consonents</h6><img src="static/img/ref/consonents.gif" alt="" class="w-100" /><hr class="my-3" /><h6>Marathi Numbers</h6><img src="static/img/ref/numbers.gif" alt="" class="w-100" /><hr class="my-3" /><a href="/" class="text-light text-right d-flex justify-content-end"><button class="btn btn-light">Homepage</button></a></div><!-- Footer Code --><navclass="navbar navbar-light bg-primary sticky-bottom text-light d-flex justify-content-center"><p class="text-light text-center">Dataset Link :<aclass="text-light"href="https://archive.ics.uci.edu/ml/datasets/Devanagari+Handwritten+Character+Dataset">https://archive.ics.uci.edu/ml/datasets/Devanagari+Handwritten+Character+Dataset</a><br />Made with ?? by<a href="https://github.com/Mayank-MP05" class="text-light">@Mayank_MP5</a></p></nav></body> </html>We are using the DrawingBoard.js to create a blank drawable drawing board you can read about it more here
我們正在使用DrawingBoard.js創(chuàng)建一個空白的可繪制繪圖板,您可以在此處內(nèi)容
https://leimi.github.io/drawingboard.js/
https://leimi.github.io/drawingboard.js/
<!DOCTYPE html> <html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>Marathi letter recognition | DL Project</title><linkrel="stylesheet"href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css"/><link rel="stylesheet" href="static/drawing-board/drawingboard.min.css" /><link rel="stylesheet" href="static/css/comman.css" /></head><body><!-- Header Code --><nav class="navbar navbar-light bg-primary"><a class="d-flex navbar-brand" href="#"><imgsrc="static/img/logo.png"width="50"height="50"class="d-inline-block align-top"alt=""style="border-radius: 50%;"/><h3 class="text-light px-2">Marathi Handwritten Letter Recognition</h3></a><div class="text-right"><a href="./ref" class="text-light"><button class="btn btn-light">Reference Sheet</button></a></div></nav><!-- Body araa --><div class="container py-2"><div class="row"><div class="col-5"><h6>Draw that Character on Board below</h6><divclass="board drawing-board square-board m-2"id="simple-board"></div><div class="d-inline w-100 text-center btn-socket"><button class="btn btn-danger" onclick="ResetBG()">Clear</button><buttontype="submit"class="btn btn-success"onclick="GetImageURL()">Predict</button></div></div><div class="col-7"><h5>Predictions from Drawn Images :</h5><table class="table table-bordered"><thead class="thead-dark"><tr><th scope="col">#</th><th scope="col">Drawn Image</th><th scope="col">Prediction</th></tr></thead><tbody><tr><th scope="row" id="current-count">Current</th><td id="current-img">Loading...</td><td id="current-prediction">Loading...</td></tr><tr><th scope="row">Previous</th><td><imgsrc="http://localhost:5000/image/1343"alt=""class="thumb-img"/></td><td>character_06_cha</td></tr><tr><th scope="row">Previous</th><td><imgsrc="http://localhost:5000/image/9386"alt=""class="thumb-img"/></td><td>character_25_ma</td></tr><tr><th scope="row">Previous</th><td><imgsrc="http://localhost:5000/image/5376"alt=""class="thumb-img"/></td><td>character_02_kha</td></tr></tbody></table></div></div></div><!-- Footer Code --><navclass="navbar navbar-light bg-primary sticky-bottom text-light d-flex justify-content-center"><p class="text-light text-center">Dataset Link :<aclass="text-light"href="https://archive.ics.uci.edu/ml/datasets/Devanagari+Handwritten+Character+Dataset">https://archive.ics.uci.edu/ml/datasets/Devanagari+Handwritten+Character+Dataset</a><br />Made with ?? by<a href="https://github.com/Mayank-MP05" class="text-light">@Mayank_MP5</a></p></nav><script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script><script src="static/drawing-board/drawingboard.min.js"></script><script src="static/js/drawing-board-controls.js"></script><script src="static/js/imageAndTextUpdate.js"></script></body> </html>On the Home page there is Drawing Board on the Left and the Prediction column on the right there are 2 buttons below the drawing board one for clearing the board and other for prediction
在主頁上,左側(cè)是制圖板,右側(cè)是“預(yù)測”列,制圖板下方有2個按鈕,一個用于清除板,另一個用于預(yù)測
let’s dive into the front end javascript code for drawing board and clearing
讓我們深入研究用于畫板和清理的前端javascript代碼
var simpleBoard = new DrawingBoard.Board("simple-board", {controls: false,background: "#000",color: "#fff",size: 20,webStorage: false, }); //simpleBoard.addControl("Download"); //if the DrawingBoard.Control.Download class exists//listen to an event simpleBoard.ev.bind("board:reset", why);//stop listening to itsimpleBoard.ev.unbind("board:reset", why);function why() {alert("OH GOD WHY"); }const ResetBG = () => {console.log("Reset BG called");simpleBoard.resetBackground(); };const GetImageURL = () => {url = simpleBoard.getImg();console.log("Image Request Sent ...");$.ajax({type: "POST",url: "/upload",data: {imageBase64: url,},}).done(function (e) {updateTable(e);ResetBG();console.log(e);}); };We created the instance of the drawing board class board with a black background and white pointer
我們用黑色背景和白色指針創(chuàng)建了繪圖板類板的實例
ResetBG: is used to clear the board to full black
ResetBG :用于將板清除為全黑
GetImageURL: used to get Image URI and send it to backend /upload route via post request to the server and clearing the canvas after sending that
GetImageURL :用于獲取圖像URI并將其通過后請求發(fā)送到服務(wù)器的后端/上傳路由,并在發(fā)送后清除畫布
const updateTable = (obj) => {console.log("Update Table called");const imgParent = document.getElementById("current-img");const predictParent = document.getElementById("current-prediction");imageID = obj.imageID;prediction = obj.prediction;url = `http://localhost:5000/image/${imageID}`;img = `<img src="${url}" class="thumb-img">`;imgParent.innerHTML = img;predictParent.innerHTML = prediction; };we need to update the prediction coming from the backend on the front end table and that task is done by updateTable function it updates image URL and Image ID coming from the server
我們需要更新來自前端表后端的預(yù)測,并且該任務(wù)由updateTable函數(shù)完成,它會更新來自服務(wù)器的圖像URL和圖像ID
Here is the Final Output of what we built in this tutorial
這是我們在本教程中構(gòu)建的內(nèi)容的最終輸出
you can take look at code here in the web-app directory :
您可以在web-app目錄中查看以下代碼:
Thanks for Reading!
謝謝閱讀!
翻譯自: https://medium.com/ai-in-plain-english/handwritten-marathi-hindi-letter-writing-and-detection-using-deep-learning-web-project-2552ed429dbe
總結(jié)
以上是生活随笔為你收集整理的使用深度学习Web项目的手写Marathi印地语字母书写和检测的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python数据可视化案例 淘宝粽子_P
- 下一篇: 淘宝商品数据清洗及预处理