偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

干貨 | 手把手教你用115行代碼做個數(shù)獨解析器!

人工智能 機(jī)器學(xué)習(xí)
這里有一份數(shù)獨解析教程,等待你查收~ 喜歡收藏硬核干貨的小伙伴看過來。

 

你也是數(shù)獨愛好者嗎?

Aakash Jhawar和許多人一樣,樂于挑戰(zhàn)新的難題。上學(xué)的時候,他每天早上都要玩數(shù)獨。長大后,隨著科技的進(jìn)步,我們可以讓計算機(jī)來幫我們解數(shù)獨了!只需要點擊數(shù)獨的圖片,它就會為你填滿全部九宮格。

叮~ 這里有一份數(shù)獨解析教程,等待你查收~ 喜歡收藏硬核干貨的小伙伴看過來~

我們都知道,數(shù)獨由9×9的格子組成,每行、列、宮各自都要填上1-9的數(shù)字,要做到每行、列、宮里的數(shù)字都不重復(fù)。

可以將解析數(shù)獨的整個過程分成3步:

第一步:從圖像中提取數(shù)獨

第二步:提取圖像中出現(xiàn)的每個數(shù)字

第三步:用算法計算數(shù)獨的解

第一步:從圖像中提取數(shù)獨

首先需要進(jìn)行圖像處理。

1、對圖像進(jìn)行預(yù)處理

首先,我們應(yīng)用高斯模糊的內(nèi)核大小(高度,寬度)為9的圖像。注意,內(nèi)核大小必須是正的和奇數(shù)的,并且內(nèi)核必須是平方的。然后使用11個最近鄰像素自適應(yīng)閾值。 

  1. proc = cv2.GaussianBlur(img.copy(),(9,9),0)  
  2. proc = cv2.adaptiveThreshold(proc,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY,11,2) 

為了使網(wǎng)格線具有非零像素值,我們顛倒顏色。此外,把圖像放大,以增加網(wǎng)格線的大小。 

  1. proc = cv2.bitwise_not(proc,proc)     
  2. kernel = np.array([[0。,1.,0.],[1.,1.,1.],[0.,1.,0.]] ,np.uint8)  
  3. proc = cv2.dilate(proc,kernel) 

       

閾值化后的數(shù)獨圖像

2、找出最大多邊形的角

下一步是尋找圖像中最大輪廓的4個角。所以需要找到所有的輪廓線,按面積降序排序,然后選擇面積最大的那個。 

  1. _, contours, h = cv2.findContours(img.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)  
  2. contours = sorted(contours, key=cv2.contourArea, reverse=True 
  3. polygon = contours[0] 

使用的操作符。帶有max和min的itemgetter允許我們獲得該點的索引。每個點都是有1個坐標(biāo)的數(shù)組,然后[0]和[1]分別用于獲取x和y。

右下角點具有最大的(x + y)值;左上角有點最小(x + y)值;左下角則具有最小的(x - y)值;右上角則具有最大的(x - y)值。 

  1. bottom_right, _ = max(enumerate([pt[0][0] + pt[0][1] for pt in  
  2.                       polygon]), key=operator.itemgetter(1))  
  3. top_left, _ = min(enumerate([pt[0][0] + pt[0][1] for pt in  
  4.                   polygon]), key=operator.itemgetter(1))  
  5. bottom_left, _ = min(enumerate([pt[0][0] - pt[0][1] for pt in  
  6.                      polygon]), key=operator.itemgetter(1))  
  7. top_right, _ = max(enumerate([pt[0][0] - pt[0][1] for pt in  
  8.                    polygon]), key=operator.itemgetter(1)) 

現(xiàn)在我們有了4個點的坐標(biāo),然后需要使用索引返回4個點的數(shù)組。每個點都在自己的一個坐標(biāo)數(shù)組中。 

  1. [polygon[top_left][0], polygon[top_right][0], polygon[bottom_right][0], polygon[bottom_left][0]] 

最大多邊形的四個角

3、裁剪和變形圖像

有了數(shù)獨的4個坐標(biāo)后,我們需要剪裁和彎曲一個矩形部分,從一個圖像變成一個類似大小的正方形。由左上、右上、右下和左下點描述的矩形。

注意:將數(shù)據(jù)類型顯式設(shè)置為float32或‘getPerspectiveTransform’會引發(fā)錯誤。 

  1. top_left, top_right, bottom_right, bottom_left = crop_rect[0], crop_rect[1], crop_rect[2], crop_rect[3]  
  2. src = np.array([top_left, top_right, bottom_right, bottom_left], dtypefloat32 )   
  3. side = max([  distance_between(bottom_right, top_right),   
  4.             distance_between(top_left, bottom_left),  
  5.             distance_between(bottom_right, bottom_left),     
  6.             distance_between(top_left, top_right) ]) 

用計算長度的邊來描述一個正方形,這是要轉(zhuǎn)向的新視角。然后要做的是通過比較之前和之后的4個點來得到用于傾斜圖像的變換矩陣。最后,再對原始圖像進(jìn)行變換。 

  1. dst = np.array([[0, 0], [side - 1, 0], [side - 1, side - 1], [0, side - 1]], dtypefloat32 )  
  2. m = cv2.getPerspectiveTransform(src, dst)  
  3. cv2.warpPerspective(img, m, (int(side), int(side))) 

裁剪和變形后的數(shù)獨圖像

4、從正方形圖像中推斷網(wǎng)格

從正方形圖像推斷出81個單元格。我們在這里交換 j 和 i ,這樣矩形就被存儲在從左到右讀取的列表中,而不是自上而下。 

  1. squares = []   
  2. side = img.shape[:1]   
  3. sideside = side[0] / 9 
  4. for j in range(9):  
  5.     for i in range(9):  
  6.         p1 = (i * side, j * side)  #Top left corner of a box    
  7.         p2 = ((i + 1) * side, (j + 1) * side)  #Bottom right corner       
  8.          squares.append((p1, p2)) return squares 

5、得到每一位數(shù)字

下一步是從其單元格中提取數(shù)字并構(gòu)建一個數(shù)組。 

  1. digits = []  
  2. img = pre_process_image(img.copy(), skip_dilate=True 
  3. for square in squares:  
  4.     digits.append(extract_digit(img, square, size)) 

extract_digit 是從一個數(shù)獨方塊中提取一個數(shù)字(如果有的話)的函數(shù)。它從整個方框中得到數(shù)字框,使用填充特征查找來獲得框中間的最大特征,以期在邊緣找到一個屬于該數(shù)字的像素,用于定義中間的區(qū)域。接下來,需要縮放并填充數(shù)字,讓適合用于機(jī)器學(xué)習(xí)的數(shù)字大小的平方。同時,我們必須忽略任何小的邊框。 

  1. def extract_digit(img, rect, size):  
  2.     digit = cut_from_rect(img, rect)  
  3.     h, w = digit.shape[:2]  
  4.     margin = int(np.mean([h, w]) / 2.5)  
  5.     _, bbox, seed = find_largest_feature(digit, [margin, margin], [w  
  6.     - margin, h - margin])  
  7.     digit = cut_from_rect(digit, bbox)   
  8.     w = bbox[1][0] - bbox[0][0]  
  9.     h = bbox[1][1] - bbox[0][1]  
  10.     if w > 0 and h > 0 and (w * h) > 100 and len(digit) > 0:  
  11.         return scale_and_centre(digit, size, 4)  
  12.     else:  
  13.         return np.zeros((size, size), np.uint8) 

      

最后的數(shù)獨的形象

現(xiàn)在,我們有了最終的數(shù)獨預(yù)處理圖像,下一個任務(wù)是提取圖像中的每一位數(shù)字,并將其存儲在一個矩陣中,然后通過某種算法計算出數(shù)獨的解。

第二步:提取圖像中出現(xiàn)的每個數(shù)字

對于數(shù)字識別,我們將在MNIST數(shù)據(jù)集上訓(xùn)練神經(jīng)網(wǎng)絡(luò),該數(shù)據(jù)集包含60000張0到9的數(shù)字圖像。從導(dǎo)入所有庫開始。 

  1. import numpy  
  2. import cv2from keras.datasets   
  3. import mnistfrom keras.models   
  4. import Sequentialfrom keras.layers   
  5. import Densefrom keras.layers   
  6. import Dropoutfrom keras.layers   
  7. import Flattenfrom keras.layers.convolutional   
  8. import Conv2Dfrom keras.layers.convolutional   
  9. import MaxPooling2Dfrom keras.utils   
  10. import np_utilsfrom keras   
  11. import backend as K  
  12. import matplotlib.pyplot as plt 

需要修復(fù)隨機(jī)種子以確保可重復(fù)性。 

  1. K.set_image_dim_ordering( th )  
  2. seed = 7numpy.random.seed(seed)  
  3. (X_train, y_train), (X_test, y_test) = mnist.load_data() 

然后將圖像重塑為樣本*像素*寬度*高度,并輸入從0-255規(guī)范化為0-1。在此之后,對輸出進(jìn)行熱編碼。 

  1. X_trainX_train = X_train.reshape(X_train.shape[0], 1, 28,  
  2.                            28).astype( float32 )  
  3. X_testX_test = X_test.reshape(X_test.shape[0], 1, 28,  
  4.                            28).astype( float32 )   
  5. X_trainX_train = X_train / 255  
  6. X_testX_test = X_test / 255 
  7. y_train = np_utils.to_categorical(y_train)  
  8. y_test = np_utils.to_categorical(y_test)  
  9. num_classes = y_test.shape[1] 

接下來,我們將創(chuàng)建一個模型來預(yù)測手寫數(shù)字。 

  1. model = Sequential()  
  2. model.add(Conv2D(32, (5, 5), input_shape=(1, 28, 28),  
  3.           activationrelu ))  
  4. model.add(MaxPooling2D(pool_size=(2, 2)))model.add(Conv2D(16, (3,  
  5.           3), activationrelu ))  
  6. model.add(MaxPooling2D(pool_size=(2, 2))) 
  7. model.add(Dropout(0.2)) 
  8. model.add(Flatten())  
  9. model.add(Dense(128, activationrelu ))  
  10. model.add(Dense(64, activationrelu ))  
  11. model.add(Dense(num_classes, activationsoftmax )) 

模型總結(jié)

在創(chuàng)建模型之后,需要進(jìn)行編譯,使其適合數(shù)據(jù)集并對其進(jìn)行評估。 

  1. model.compile(losscategorical_crossentropy , optimizeradam ,  
  2.                metrics=[ accuracy ])  
  3. model.fit(X_train, y_train, validation_data=(X_test, y_test),  
  4.                epochs=10batch_size=200 
  5. scores = model.evaluate(X_test, y_test, verbose=0 
  6. print("Large CNN Error: %.2f%%" % (100-scores[1]*100)) 

現(xiàn)在,可以測試上面創(chuàng)建的模型了。 

  1. test_images = X_test[1:5]  
  2. test_imagestest_images = test_images.reshape(test_images.shape[0], 28, 28)  
  3. print ("Test images shape: {}".format(test_images.shape))  
  4. for i, test_image in enumerate(test_images, start=1):  
  5.     org_image = test_image  
  6.     test_imagetest_image = test_image.reshape(1,1,28,28)  
  7.     prediction = model.predict_classes(test_image, verbose=0 
  8.     print ("Predicted digit: {}".format(prediction[0]))  
  9.     plt.subplot(220+i)  
  10.     plt.axis( off )  
  11.     plt.title("Predicted digit: {}".format(prediction[0]))  
  12.     plt.imshow(org_image, cmap=plt.get_cmap( gray ))  
  13. plt.show() 

手寫體數(shù)字分類模型的預(yù)測數(shù)字

神經(jīng)網(wǎng)絡(luò)的精度為98.314%!最后,保存序列模型,這樣就不必在需要使用它的時候反復(fù)訓(xùn)練了。 

  1. # serialize model to JSON  
  2. modelmodel_json = model.to_json()  
  3. with open("model.json", "w") as json_file:  
  4.     json_file.write(model_json) 
  5. # serialize weights to HDF5  
  6. model.save_weights("model.h5")  
  7. print("Saved model to disk") 

更多關(guān)于手寫數(shù)字識別的信息:

https://github.com/aakashjhawar/Handwritten-Digit-Recognition

下一步是加載預(yù)先訓(xùn)練好的模型。 

  1. json_file = open( model.json ,  r )  
  2. loaded_model_json = json_file.read()  
  3. json_file.close()  
  4. loaded_model = model_from_json(loaded_model_json)  
  5. loaded_model.load_weights("model.h5") 

調(diào)整圖像大小,并將圖像分割成9x9的小圖像。每個小圖像的數(shù)字都是從1-9。 

  1. sudoku = cv2.resize(sudoku, (450,450))  
  2. grid = np.zeros([9,9])  
  3. for i in range(9):  
  4.     for j in range(9):  
  5.         image = sudoku[i*50:(i+1)*50,j*50:(j+1)*50]  
  6.         if image.sum() > 25000:      
  7.             grid[i][j] = identify_number(image)  
  8.         else:  
  9.             grid[i][j] = 0      
  10. gridgrid =  grid.astype(int) 

identify_number 函數(shù)拍攝數(shù)字圖像并預(yù)測圖像中的數(shù)字。 

  1. def identify_number(image):  
  2.     image_resize = cv2.resize(image, (28,28))    # For plt.imshow  
  3.     image_resizeimage_resize_2 = image_resize.reshape(1,1,28,28)    # For input to model.predict_classes  
  4. #    cv2.imshow( number , image_test_1)  
  5.     loaded_modelloaded_model_pred = loaded_model.predict_classes(image_resize_2   
  6.                                                       , verbose = 0 
  7.     return loaded_model_pred[0]  

完成以上步驟后,數(shù)獨網(wǎng)格看起來是這樣的:

提取的數(shù)獨

第三步:用回溯算法計算數(shù)獨的解

我們將使用回溯算法來計算數(shù)獨的解。

在網(wǎng)格中搜索仍未分配的條目。如果找到引用參數(shù)行,col 將被設(shè)置為未分配的位置,而 true 將被返回。如果沒有未分配的條目保留,則返回false。“l” 是 solve_sudoku 函數(shù)傳遞的列表變量,用于跟蹤行和列的遞增。 

  1. def find_empty_location(arr,l):  
  2.     for row in range(9):  
  3.         for col in range(9):  
  4.             if(arr[row][col]==0):  
  5.                 l[0]=row  
  6.                 l[1]=col  
  7.                 return True  
  8.     return False 

返回一個boolean,指示指定行的任何賦值項是否與給定數(shù)字匹配。 

  1. def used_in_row(arr,row,num):  
  2.     for i in range(9):     
  3.         if(arr[row][i] == num):    
  4.             return True  
  5.     return False 

返回一個boolean,指示指定列中的任何賦值項是否與給定數(shù)字匹配。 

  1. def used_in_col(arr,col,num):  
  2.     for i in range(9):    
  3.         if(arr[i][col] == num):   
  4.             return True  
  5.     return False 

返回一個boolean,指示指定的3x3框內(nèi)的任何賦值項是否與給定的數(shù)字匹配。 

  1. def used_in_box(arr,row,col,num):  
  2.     for i in range(3):  
  3.         for j in range(3):  
  4.             if(arr[i+row][j+col] == num):      
  5.             return True  
  6.      return False 

檢查將num分配給給定的(row, col)是否合法。檢查“ num”是否尚未放置在當(dāng)前行,當(dāng)前列和當(dāng)前3x3框中。 

  1. def check_location_is_safe(arr,row,col,num):  
  2.     return not used_in_row(arr,row,num) and   
  3.            not used_in_col(arr,col,num) and   
  4.            not used_in_box(arr,row - row%3,col - col%3,num) 

采用部分填入的網(wǎng)格,并嘗試為所有未分配的位置分配值,以滿足數(shù)獨解決方案的要求(跨行、列和框的非重復(fù))。“l” 是一個列表變量,在 find_empty_location 函數(shù)中保存行和列的記錄。將我們從上面的函數(shù)中得到的行和列賦值給列表值。 

  1. def solve_sudoku(arr):  
  2.     l=[0,0]   
  3.     if(not find_empty_location(arr,l)):  
  4.         return True   
  5.     row=l[0]  
  6.     col=l[1]   
  7.     for num in range(1,10):   
  8.         if(check_location_is_safe(arr,row,col,num)):   
  9.             arr[row][col]=num   
  10.             if(solve_sudoku(arr)):   
  11.                 return True   
  12.             # failure, unmake & try again   
  13.             arr[row][col] = 0   
  14.     return False 

最后一件事是print the grid。 

  1. def print_grid(arr):  
  2.     for i in range(9):  
  3.         for j in range(9):    
  4.             print (arr[i][j])   
  5.          print (  ) 

最后,把所有的函數(shù)整合在主函數(shù)中。 

  1. def sudoku_solver(grid):  
  2.     if(solve_sudoku(grid)):  
  3.         print( --- )  
  4.     else:  
  5.         print ("No solution exists")  
  6.     gridgrid = grid.astype(int) 
  7.      return grid 

這個函數(shù)的輸出將是最終解出的數(shù)獨。

最終的解決方案

當(dāng)然,這個解決方案絕不是萬無一失的,處理圖像時仍然會出現(xiàn)一些問題,要么無法解析,要么解析錯誤導(dǎo)致無法處理。不過,我們的目標(biāo)是探索新技術(shù),從這個角度來看,這個項目還是有價值的。 

 

責(zé)任編輯:龐桂玉 來源: 機(jī)器學(xué)習(xí)算法與Python學(xué)習(xí)
相關(guān)推薦

2017-10-29 21:43:25

人臉識別

2021-08-09 13:31:25

PythonExcel代碼

2017-10-27 10:29:35

人臉識別UbuntuPython

2022-10-19 14:30:59

2011-03-28 16:14:38

jQuery

2021-02-04 09:00:57

SQLDjango原生

2021-02-06 14:55:05

大數(shù)據(jù)pandas數(shù)據(jù)分析

2020-08-12 07:41:39

SQL 優(yōu)化語句

2022-06-30 16:10:26

Python計時器裝飾器

2022-08-04 10:39:23

Jenkins集成CD

2009-04-22 09:17:19

LINQSQL基礎(chǔ)

2021-05-10 06:48:11

Python騰訊招聘

2021-01-21 09:10:29

ECharts柱狀圖大數(shù)據(jù)

2021-01-08 10:32:24

Charts折線圖數(shù)據(jù)可視化

2012-01-11 13:40:35

移動應(yīng)用云服務(wù)

2021-08-02 23:15:20

Pandas數(shù)據(jù)采集

2020-03-08 22:06:16

Python數(shù)據(jù)IP

2021-02-02 13:31:35

Pycharm系統(tǒng)技巧Python

2021-12-11 20:20:19

Python算法線性

2022-05-11 10:45:21

SpringMVC框架Map
點贊
收藏

51CTO技術(shù)棧公眾號