手把手教你实现解密数独的web应用程序
實現的功能:通過傳入數獨圖片從而獲取數獨結果并展示在web界面
首先看一下效果圖
第一步:打開數獨界面,輸入一張數獨圖片(嗯~網站搭建略顯粗糙,就是簡單的通過post請求上傳一張圖片)
第二步,點擊提交,然后默默等待結果就可以啦
?對結果稍稍做了一下美化,效果還算一般般吧
要實現這樣的小程序需要什么樣的操作呢
一、首先你需要編寫一個解密數獨的程序,代碼如下,簡單來講就是通過不斷嘗試暴力求解。(簡單粗暴)完整的源碼鏈接在文末
class Sudoku(object):def __init__(self, matrix):self.in_matrix = matrixself.matrix = matrixself.index_list = self.__get_index() # 獲取待解密的數值列表[raw,line,[values]]def get_result(self):out = self.__check() # 初步檢查數獨是否符合要求if out is False:print("不是正確的數獨!")return self.in_matrix, Falseresult, index = self.__try_values(0)while result is not True: # 如果嘗試失敗,再嘗試上一個值result, index = self.__try_values(index - 1)if result is False and index == 0: # 如果第一個值都嘗試完但是還沒解出來,表示無解print("此數獨無解!")return self.in_matrix, Falsereturn self.matrix, True讓我們運行一個例子,結果如下
第二步、也是最重要的部分,如何通過圖片直接得到數獨的輸入而不是自己手動去敲呢,畢竟9*9=81個數獨輸入完全手敲人都要麻了,對此,我們可以采用深度學習模型去訓練一個可以自動識別數獨輸入圖片的模型,在此,作者選用了VGG去訓練一個自己的分類網絡模型
1.眾所周知,要訓練模型,數據肯定是必須的,如果一張一張的去網上下載圖片,對于一個程序員來說肯定是不允許的,所以在此采用爬蟲簡單獲取了所需要的訓練數據
爬蟲抓取圖片可以參考基于Python爬取Bing圖片_錢彬 (Qian Bin)的博客-CSDN博客_爬取bing的數據解扣子
下載的圖片數據如下:
????????很明顯,我們所需的爬蟲圖片是9*9的方格,但是部分圖片并不符合我們的要求,對此,我們需要對數據做篩選,為了保證模型輸入的圖片符合要求,需要訓練一個模型用來檢查數據數據是否符合要求
2.將數據劃分為符合要求和不符合要求的兩個類別,分別放在兩個文件夾
開始訓練一個數據檢查模型
VGG模型的訓練可以參考這位博主:神經網絡學習小記錄19——微調VGG分類模型訓練自己的數據(貓狗數據集)_Bubbliiiing的博客-CSDN博客_神經網絡微調
3.得到符合要求的數據后我們要如何將圖片轉化為數獨程序的輸入呢,對此,我們可以使用opencv對圖像進行一些簡單的處理,將圖片切分成9*9的方格,每一個方格表示一個輸入數據,數據的處理過程如下:
1)使用邊緣檢測將數獨圖片的矩形框提取出來
2)將圖片裁剪為9*9的小方格
3)將每一種數字作為一個類別進行訓練
裁剪方式效果如下
得到的結果:
?
?數據集目錄結構,每一個標簽代表一種數值,0表示空數據
最后就和上面的步驟一樣,再次訓練一個模型即可
第三步、將訓練完成的模型部署到web端
1.首先我們需要搭建一個網站用來展示我們的模型,在此,我選擇了html文本,搭建一個通過post請求上傳圖片的功能
可以參考:Flask實現圖片的上傳、下載及展示_Java知音_的博客-CSDN博客_vue flask 后臺圖像下載顯示
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>Title</title> </head><body><div><form method="post" action="http://localhost:5000/get_result" enctype="multipart/form-data"><input type="file" size="30" name="photo"/><br><input type="text" class="txt_input" name="name" style="margin-top:15px;"/><input type="submit" value="提交信息" class="button-new" style="margin-top:15px;"/></form></div><a href="http://127.0.0.1:5000/app">重新選擇</a><a href="http://127.0.0.1:5000/">返回首頁</a></body> </html>結果展示
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>Title</title> </head> <body><p>讀取成功</p><p>運行耗時:{{ time }}秒</p> <table><tr> <td><p>處理后的輸入圖像</p><img src="data:;base64,{{ img_in}}"></td> <td> <p>得到的輸出結果 </p><img src="data:;base64,{{ result_out }}"></td> </tr></table><a href="http://127.0.0.1:5000/app">重新選擇</a><a href="http://127.0.0.1:5000/">返回首頁</a> </body> </html>2.將我們的模型部署到web端,將post請求的圖片解碼并傳入我們的模型,經過預處理和模型預測得到最后的輸出結果,然后經過處理后展示在web界面
主程序
@app.route('/get_result', methods=['POST'], strict_slashes=False) def api_upload():t1 = time.time()data_file = request.files['photo']if data_file and allowed_file(data_file.filename):pil_img = Image.open(data_file)pil_img = pil_img.convert('RGB')img = np.asarray(pil_img)detect_img = img_detect.img_detect(img)img_in = return_img_stream(detect_img, SIZE)detect = detect_model.inference(detect_img)if detect == 1:cut_imgs = img_cut.img_cut(detect_img)pred = num_model.inference(cut_imgs)# result_in = show_result(pred)# result_in = return_img_stream(result_in, SIZE)sudo = Sudoku(pred)result, msg = sudo.get_result()if msg is False:return render_template('error_request.html', img_in=img_in, error="此數獨無解")img_result = show_result(result)img_out = img_detect.img_detect(img_result)result_out = return_img_stream(img_out, SIZE)t2 = time.time()return render_template('show_result.html', img_in=img_in, result_out=result_out, time=str(t2 - t1))else:return render_template('error_request.html', img_in=img_in, error="圖片不符合解密要求")else:return render_template('error_format.html', error="圖片格式錯誤")將結果轉化為圖片展示
def show_result(result):result.reverse()plt.figure(figsize=(9, 9)) # 設置畫布大小ax = plt.gca() # 獲取畫布x_major_locator = MultipleLocator(1) # 定義刻度值y_major_locator = MultipleLocator(1)ax.xaxis.set_major_locator(x_major_locator) # 設置刻度值ax.yaxis.set_major_locator(y_major_locator)cm = plt.cm.get_cmap('rainbow', 10) # 分為7級ax.set(xlim=(0, 9), ylim=(0, 9)) # 設置想x,y刻度值區間plt.xticks([]) # 隱藏想坐標值plt.yticks([])for i, rows in enumerate(result):for j, value in enumerate(rows):plt.scatter(j + 0.5, i + 0.5, marker=',', s=3100,c=value, vmin=0, vmax=9, cmap=cm) # 畫像素塊ax.text(j + 0.5, i + 0.5, value, size=20, va="center", ha="center") # 寫文字fig = plt.gcf().canvas # 獲取當前圖像并添加畫布ag = fig.switch_backends(FigureCanvasAgg)ag.draw()A = np.asarray(ag.buffer_rgba())pil_img = Image.fromarray(A)pil_img = pil_img.convert('RGB')img = np.asarray(pil_img)return img?最后附上源碼地址:https://github.com/hyyfengshang/sukodu_app
總結
以上是生活随笔為你收集整理的手把手教你实现解密数独的web应用程序的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JavaWeb中文编码问题方法解析
- 下一篇: SPSS 24 64位安装