2016年秋-网络程序设计 学习总结
對血常規(guī)檢驗報告的OCR識別、深度學習與分析
項目背景
?????? 2016是人工智能爆發(fā)的一年,各種層出不窮的新技術(shù)、新概念讓人眼花繚亂。醫(yī)療保健領(lǐng)域中的大數(shù)據(jù)在改善患者護理以及最終實現(xiàn)合理成本方面具有巨大的潛力。大數(shù)據(jù)時代的出現(xiàn)給統(tǒng)計機器學習提供了更多的機遇,因為海量的數(shù)據(jù)更加需要統(tǒng)計、抽樣的方法。
????? 本學習孟寧老師的網(wǎng)絡(luò)程序設(shè)計課程內(nèi)容為基于神經(jīng)網(wǎng)絡(luò)的醫(yī)療輔助診斷專家系統(tǒng)設(shè)計,我和同學們都滿懷興趣和激情加入了課程的學習。同學們在分享討論中,對機器學習的相關(guān)算法、圖片和數(shù)據(jù)的處理方法都進行了學習和了解,這樣的學習方式是高效且充滿意義的。同時,對課程項目內(nèi)容也不斷地充實、完善,在此進行回顧和總結(jié)。
項目目標
?????? 能夠?qū)⑹謾C拍攝的血常規(guī)檢驗報告圖片預(yù)處理,并且實現(xiàn)圖像識別,將檢驗結(jié)果輸入到神經(jīng)網(wǎng)絡(luò),進行性別和年齡的預(yù)測。對項目進行展望,可以通過更加豐富的檢驗數(shù)據(jù),基于更加完善的深度學習模型,對對象的健康狀況給出預(yù)測。
課程中的貢獻與學習成果
課程貢獻:
與同學們分享了機器學習中的決策樹算法,并進行了具體應(yīng)用的演示。
學習成果:
(1)通過參與同學們的分享和討論,對機器學習的方法有了基礎(chǔ)地學習和認識。學習了常見的機器學習算法(SVM、隨機森林、決策樹、感知機、Adaboost等)的原理和特性。感受到了opencv在圖像預(yù)處理方面的強大功能,學習了本項目中對圖片進行處理的方法原理,掌握了利用ocr方法進行圖像文本識別的方法。
(2)在對神經(jīng)網(wǎng)絡(luò)的學習中,掌握了BP神經(jīng)網(wǎng)絡(luò)的算法原理。通過同學們的分享交流,對深度學習的常用框架caffe、tensorflow、MxNet等有了更進一步的了解。其中,對caffe框架進行了較為深入的研究,受到啟發(fā),在工程實踐項目中采用caffe實現(xiàn)了圖像多目標檢測任務(wù)。
(3)在認真聆聽同學們對各種算法的介紹中,開拓了眼界,能夠主動思考比較各類算法和框架的有點與不足,考慮何種算法更適合應(yīng)用在何種場合,產(chǎn)生了對機器學習的濃厚興趣。
(4)在學習中,能夠與老師和同學們步調(diào)保持一致,逐步把項目完善。最終能夠成功運行項目Demo,并在同學們的指導(dǎo)和幫助下,能夠理解項目代碼。
項目部署和Demo演示
項目地址:對血常規(guī)檢驗報告的OCR識別、深度學習與分析
安裝numpy
$ sudo apt-get install Python-numpy
?
安裝Opencv
$ sudo apt-get install python-opencv
?
安裝pytesseract
$ sudo apt-get install tesseract-ocr
$ sudo pip install pytesseract
$ sudo apt-get install python-tk
$ sudo pip install pillow
?
安裝Flask框架
$ sudo pip install Flask
?
安裝mongodb
$ sudo apt-get install mongodb # 如果提示no modulename mongodb, 先執(zhí)行sudo apt-get update
$ sudo service mongodb started
$ sudo pip install pymongo
?
安裝Tensorflow
$ sudo apt-get install python-numpy
$ sudo apt-get install python-imaging
$ pip install --upgradehttps://storage.googleapis.com/tensorflow/Linux/cpu/tensorflow-0.12.0rc0-cp27-none-linux_x86_64.whl
運行
$ git clone https://git.coding.net/mengning/np2016.git
$ cd np2016
$ cd?BloodTestReportOCR
$ python view.py # upload圖像,在瀏覽器打開http://localhost:8080
訪問 localhost:8080
選擇報告單圖片上傳
點擊生成報告
點擊predict
設(shè)計分析
1.Web模塊設(shè)計
采用flask框架,json部分用來傳輸數(shù)據(jù),index.html為網(wǎng)頁編輯
app = Flask(__name__, static_url_path="") # 讀取配置文件 app.config.from_object('config') # 連接數(shù)據(jù)庫,并獲取數(shù)據(jù)庫對象 db = MongoClient(app.config['DB_HOST'], app.config['DB_PORT']).test # 將矯正后圖片與圖片識別結(jié)果(JSON)存入數(shù)據(jù)庫 def save_file(file_str, f, report_data):content = StringIO(file_str)try:mime = Image.open(content).format.lower()print 'content of mime is:', mimeif mime not in app.config['ALLOWED_EXTENSIONS']:raise IOError()except IOError:abort(400)c = dict(report_data=report_data, content=bson.binary.Binary(content.getvalue()), filename=secure_filename(f.name),mime=mime)db.files.save(c)return c['_id'], c['filename'] @app.route('/', methods=['GET', 'POST']) def index():return redirect('/index.html')
2.opencv圖片預(yù)處理,將檢驗報告圖片進行預(yù)處理并切割,為ocr識別做準備 import cv2 def digitsimg(src):#灰度化img_gray = cv2.cvtColor(src,cv2.COLOR_BGR2GRAY)#Otsu thresholding 二值化ret,result= cv2.threshold(img_gray,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)#腐蝕去除一些小的點kernel = cv2.getStructuringElement(cv2.MORPH_CROSS,(3,2))eroded = cv2.erode(result,kernel)#將結(jié)果放大便于識別result = cv2.resize(result,(128,128),interpolation=cv2.INTER_CUBIC)#腐蝕去除放大后的一些小的點eroded = cv2.erode(result,kernel)#膨脹使數(shù)字更飽滿result = cv2.dilate(eroded,kernel)#直方圖均衡化使圖像更清晰cv2.equalizeHist(result)#中值濾波去除噪點result = cv2.medianBlur(result,5)return result
3.perspect函數(shù)用于透視image,他會緩存一個透視后的opencv numpy矩陣,并返回該矩陣
def perspect(self, param=default):#載入?yún)?shù)gb_param = param[0] #必須是奇數(shù)canny_param_upper = param[1]canny_param_lower = param[2]ref_lenth_multiplier = param[3]ref_close_multiplier = param[4]kernel = cv2.getStructuringElement(cv2.MORPH_RECT,(3, 3))# 載入圖像,灰度化,開閉運算,描繪邊緣img_sp = self.img.shaperef_lenth = img_sp[0] * img_sp[1] * ref_lenth_multiplierimg_gray = cv2.cvtColor(self.img, cv2.COLOR_BGR2GRAY)img_gb = cv2.GaussianBlur(img_gray, (gb_param, gb_param), 0)closed = cv2.morphologyEx(img_gb, cv2.MORPH_CLOSE, kernel)opened = cv2.morphologyEx(closed, cv2.MORPH_OPEN, kernel)edges = cv2.Canny(opened, canny_param_lower , canny_param_upper)# 調(diào)用findContours提取輪廓contours, hierarchy = cv2.findContours(edges, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
4. filter函數(shù)返回img經(jīng)過透視過后的PIL格式的Image對象,如果緩存中有PerspectivImg則直接使用,沒有先進行透視過濾失敗則返回None
def filter(self, param=default):if self.PerspectiveImg is None:self.PerspectivImg = self.perspect(param)if self.PerspectiveImg is None:return Noneimg = Image.open(self.output_path + 'region.jpg')if not(classifier.isReport(img)):print "it is not a is Report!",classifier.isReport(self.PerspectiveImg)return Nonetry:Image.fromarray(self.PerspectivImg)except Exception:return Nonereturn Image.fromarray(self.PerspectivImg)
5. autocut函數(shù)用于剪切ImageFilter中的img成員,剪切之后臨時圖片保存在out_path,如果剪切失敗,返回-1,成功返回0
def autocut(self, num, param=default):if self.PerspectiveImg is None:self.PerspectivImg = self.filter(param)# 仍然是空,說明不是報告if self.PerspectiveImg is None:return -1#輸出年齡img_age = self.PerspectiveImg[15 : 70, 585 : 690]cv2.imwrite(self.output_path + 'age.jpg', img_age)#輸出性別img_gender = self.PerspectiveImg[15 : 58, 365 : 420]cv2.imwrite(self.output_path + 'gender.jpg', img_gender)#輸出時間img_time = self.PerspectiveImg[722 : 760, 430 : 630]cv2.imwrite(self.output_path + 'time.jpg', img_time)#轉(zhuǎn)換后的圖分辨率是已知的,所以直接從這個點開始讀數(shù)據(jù)就可以了startpoint = [199, 132]vertical_lenth = 37lateral_lenth = 80
? 6.ocr函數(shù)用于對img進行ocr識別,他會先進行剪切,之后進一步做ocr識別,返回一個json對象如果剪切失敗,則返回None
def ocr(self, num):digtitsresult = []chiresult = []# 不是報告if self.autocut(num) == -1:return None# 識別def image_to_string(image, flag=True):if flag:text = pytesseract.image_to_string(Image.fromarray(image), config='-psm 7 digits')else:text = pytesseract.image_to_string(Image.fromarray(image), lang='chi_sim', config=' -psm 7 Bloodtest')return text# 讀取圖片def read(url):image = cv2.imread(url)return image# load json examplewith open('bloodtestdata.json') as json_file:data = json.load(json_file)# 識別檢測項目編號及數(shù)字for i in range(num):item = read('temp_pics/p' + str(i) + '.jpg')item_num = classifier.getItemNum(item)image = read('temp_pics/data' + str(i) + '.jpg')image = imgproc.digitsimg(image)digtitstr = image_to_string(image)digtitstr = digtitstr.replace(" ", '')digtitstr = digtitstr.replace("-", '')digtitstr = digtitstr.strip(".")data['bloodtest'][item_num]['value'] = digtitstrjson_data = json.dumps(data,ensure_ascii=False,indent=4)return json_data
切割后的數(shù)據(jù):
利用TensorFlow框架進行模型訓練和預(yù)測:
模型定義(以年齡屬性為例)
??? x_sex = tf.placeholder("float", [None, n_input])y_sex = tf.placeholder("float", [None, n_classes_sex])def multilayer_perceptron_sex(x_sex, weights_sex, biases_sex):# Hidden layer with RELU activationlayer_1 = tf.add(tf.matmul(x_sex, weights_sex['h1']), biases_sex['b1'])layer_1 = tf.nn.relu(layer_1)# Hidden layer with RELU activationlayer_2 = tf.add(tf.matmul(layer_1, weights_sex['h2']), biases_sex['b2'])layer_2 = tf.nn.relu(layer_2)# Output layer with linear activationout_layer = tf.matmul(layer_2, weights_sex['out']) + biases_sex['out']return out_layerweights_sex = {'h1': tf.Variable(tf.random_normal([n_input, n_hidden_1_sex])),'h2': tf.Variable(tf.random_normal([n_hidden_1_sex, n_hidden_2_sex])),'out': tf.Variable(tf.random_normal([n_hidden_2_sex, n_classes_sex]))}biases_sex = {'b1': tf.Variable(tf.random_normal([n_hidden_1_sex])),'b2': tf.Variable(tf.random_normal([n_hidden_2_sex])),'out': tf.Variable(tf.random_normal([n_classes_sex]))}pred_sex = multilayer_perceptron_sex(x_sex, weights_sex, biases_sex)
模型訓練
# 激活計算圖 sess.run(init_op) # 啟動隊列 threads = tf.train.start_queue_runners(sess=sess) # 迭代次數(shù) = 10000 for i in range(10000):# batchimage, label = sess.run([img_batch, label_batch])# 輸出局部正確率if i % 100 == 0:train_accuracy = accuracy.eval(feed_dict={x: image, y_:dense_to_one_hot(label)})print("step %d, training accuracy %g" % (i, train_accuracy))result = sess.run(merged,feed_dict={x:image,y_:dense_to_one_hot(label)})writer.add_summary(result,i)train_step.run(feed_dict={x: image, y_: dense_to_one_hot(label)}) # 加載測試集 test_img, test_label = sess.run([test_img_batch, test_label_batch]) # 輸出整體正確率 print("test accuracy %g" % accuracy.eval(feed_dict={x: test_img, y_: dense_to_one_hot(test_label)})) # 保存模型 save_path = saver.save(sess, cwd + "/ckpt_sex/sex.ckpt", write_meta_graph=None) print("Model saved in file: %s" % save_path)
訓練后產(chǎn)生模型文件model.ckpt.data-00000-of-00001和model.ckpt.index
調(diào)用訓練好的模型進行預(yù)測
saver.restore(sess, "./model.ckpt") print ("load model success!") p_sex = sess.run(pred_sex, feed_dict={x_sex: data_predict}) p_age = sess.run(pred_age, feed_dict={x_age: data_predict})
收獲與感悟
??????? 在這門課的學習過程中,雖然對項目所涉及到的工具和方法還沒有達到精通的程度,但是收獲是巨大的。
??????? 首先,在與同學們的分享交流中,讓我體會到了分享的快樂。在課程的開始階段,我與同學們分享了我對機器學習算法中決策樹的理解和應(yīng)用,在分享準備過程中也加深了我對知識的掌握程度。在其他同學分享知識和項目進展的過程中,也讓我收獲了之前沒有涉及到的方法,對于我在項目中遇到的疑問也能夠得到很好解答。這樣的學習方式比自己閉門造車高效許多。
??????? 其次,項目中基于opencv對圖片預(yù)處理的過程令我感到很神奇,這是之前從未接觸到的,不斷地去了解新方法、新技術(shù)為將來的學習和開發(fā)提供了新的思路。
??????? 最重要的是,在課程學習中接觸到了機器學習這個領(lǐng)域,在學習中收獲了很多新的思路和方法,這也指導(dǎo)我在工程實踐項目中取得突破和進步。使我認識到,機器學習是未來幾年應(yīng)用比較廣泛的方法,也激起了我在這一領(lǐng)域深入研究的興趣。計劃利用寒假期間,從算法原理到代碼實現(xiàn)對機器學習進行深入學習。
總結(jié)
以上是生活随笔為你收集整理的2016年秋-网络程序设计 学习总结的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: anaconda离线环境迁移(舍弃繁文缛
- 下一篇: Unity:实现UI上下翻动效果