日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

Python圖像識(shí)別+KNN求解數(shù)獨(dú)的實(shí)現(xiàn)

瀏覽:109日期:2022-07-05 16:06:07

Python-opencv+KNN求解數(shù)獨(dú)

最近一直在玩數(shù)獨(dú),突發(fā)奇想實(shí)現(xiàn)圖像識(shí)別求解數(shù)獨(dú),輸入到輸出平均需要0.5s。

整體思路大概就是識(shí)別出圖中數(shù)字生成list,然后求解。

輸入輸出demo

數(shù)獨(dú)采用的是微軟自帶的Microsoft sudoku軟件隨便截取的圖像,如下圖所示:

Python圖像識(shí)別+KNN求解數(shù)獨(dú)的實(shí)現(xiàn)

經(jīng)過(guò)程序求解后,得到的結(jié)果如下圖所示:

Python圖像識(shí)別+KNN求解數(shù)獨(dú)的實(shí)現(xiàn)

程序具體流程

程序整體流程如下圖所示:

Python圖像識(shí)別+KNN求解數(shù)獨(dú)的實(shí)現(xiàn)

讀入圖像后,根據(jù)求解輪廓信息找到數(shù)字所在位置,以及不包含數(shù)字的空白位置,提取數(shù)字信息通過(guò)KNN識(shí)別,識(shí)別出數(shù)字;無(wú)數(shù)字信息的在list中置0;生成未求解數(shù)獨(dú)list,之后求解數(shù)獨(dú),將信息在原圖中顯示出來(lái)。

# -*-coding:utf-8-*-import osimport cv2 as cvimport numpy as npimport time#####################################################尋找數(shù)字生成listdef find_dig_(img, train_set): if img is None: print('無(wú)效的圖片!') os._exit(0) return _, thre = cv.threshold(img, 230, 250, cv.THRESH_BINARY_INV) _, contours, hierarchy = cv.findContours(thre, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE) sudoku_list = [] boxes = [] for i in range(len(hierarchy[0])): if hierarchy[0][i][3] == 0: # 表示父輪廓為 0 boxes.append(hierarchy[0][i]) # 提取數(shù)字 nm = [] for j in range(len(boxes)): # 此處len(boxes)=81 if boxes[j][2] != -1: x, y, w, h = cv.boundingRect(contours[boxes[j][2]]) nm.append([x, y, w, h]) # 在原圖中框選各個(gè)數(shù)字 cropped = img[y:y + h, x:x + w] im = img_pre(cropped)#預(yù)處理 AF = incise(im)#切割數(shù)字圖像 result = identification(train_set, AF, 7)#knn識(shí)別 sudoku_list.insert(0, int(result))#生成list else: sudoku_list.insert(0, 0)if len(sudoku_list) == 81: sudoku_list= np.array(sudoku_list) sudoku_list= sudoku_list.reshape((9, 9)) print('old_sudoku -> n', sudoku_list) return sudoku_list, contours, hierarchy else: print('無(wú)效的圖片!') os._exit(0)#######################################################KNN算法識(shí)別數(shù)字def img_pre(cropped): # 預(yù)處理數(shù)字圖像 im = np.array(cropped) # 轉(zhuǎn)化為二維數(shù)組 for i in range(im.shape[0]): # 轉(zhuǎn)化為二值矩陣 for j in range(im.shape[1]): # print(im[i, j]) if im[i, j] != 255:im[i, j] = 1 else:im[i, j] = 0 return im# 提取圖片特征def feature(A): midx = int(A.shape[1] / 2) + 1 midy = int(A.shape[0] / 2) + 1 A1 = A[0:midy, 0:midx].mean() A2 = A[midy:A.shape[0], 0:midx].mean() A3 = A[0:midy, midx:A.shape[1]].mean() A4 = A[midy:A.shape[0], midx:A.shape[1]].mean() A5 = A.mean() AF = [A1, A2, A3, A4, A5] return AF# 切割圖片并返回每個(gè)子圖片特征def incise(im): # 豎直切割并返回切割的坐標(biāo) a = []; b = [] if any(im[:, 0] == 1): a.append(0) for i in range(im.shape[1] - 1): if all(im[:, i] == 0) and any(im[:, i + 1] == 1): a.append(i + 1) elif any(im[:, i] == 1) and all(im[:, i + 1] == 0): b.append(i + 1) if any(im[:, im.shape[1] - 1] == 1): b.append(im.shape[1]) # 水平切割并返回分割圖片特征 names = locals(); AF = [] for i in range(len(a)): names[’na%s’ % i] = im[:, range(a[i], b[i])] if any(names[’na%s’ % i][0, :] == 1): c = 0 else: for j in range(names[’na%s’ % i].shape[0]):if j < names[’na%s’ % i].shape[0] - 1: if all(names[’na%s’ % i][j, :] == 0) and any(names[’na%s’ % i][j + 1, :] == 1): c = j breakelse: c = j if any(names[’na%s’ % i][names[’na%s’ % i].shape[0] - 1, :] == 1): d = names[’na%s’ % i].shape[0] - 1 else: for j in range(names[’na%s’ % i].shape[0]):if j < names[’na%s’ % i].shape[0] - 1: if any(names[’na%s’ % i][j, :] == 1) and all(names[’na%s’ % i][j + 1, :] == 0): d = j + 1 breakelse: d = j names[’na%s’ % i] = names[’na%s’ % i][range(c, d), :] AF.append(feature(names[’na%s’ % i])) # 提取特征 for j in names[’na%s’ % i]: pass return AF# 訓(xùn)練已知圖片的特征def training(): train_set = {} for i in range(9): value = [] for j in range(15): ima = cv.imread(’E:/test_image/knn_test/{}/{}.png’.format(i + 1, j + 1), 0) im = img_pre(ima) AF = incise(im) value.append(AF[0]) train_set[i + 1] = value return train_set# 計(jì)算兩向量的距離def distance(v1, v2): vector1 = np.array(v1) vector2 = np.array(v2) Vector = (vector1 - vector2) ** 2 distance = Vector.sum() ** 0.5 return distance# 用最近鄰算法識(shí)別單個(gè)數(shù)字def knn(train_set, V, k): key_sort = [11] * k value_sort = [11] * k for key in range(1, 10): for value in train_set[key]: d = distance(V, value) for i in range(k):if d < value_sort[i]: for j in range(k - 2, i - 1, -1): key_sort[j + 1] = key_sort[j] value_sort[j + 1] = value_sort[j] key_sort[i] = key value_sort[i] = d break max_key_count = -1 key_set = set(key_sort) for key in key_set: if max_key_count < key_sort.count(key): max_key_count = key_sort.count(key) max_key = key return max_key# 生成數(shù)字def identification(train_set, AF, k): result = ’’ for i in AF: key = knn(train_set, i, k) result = result + str(key) return result#############################################################################################################求解數(shù)獨(dú)def get_next(m, x, y): # 獲得下一個(gè)空白格在數(shù)獨(dú)中的坐標(biāo)。 :param m 數(shù)獨(dú)矩陣 :param x 空白格行數(shù) :param y 空白格列數(shù) ''' for next_y in range(y + 1, 9): # 下一個(gè)空白格和當(dāng)前格在一行的情況 if m[x][next_y] == 0: return x, next_y for next_x in range(x + 1, 9): # 下一個(gè)空白格和當(dāng)前格不在一行的情況 for next_y in range(0, 9): if m[next_x][next_y] == 0:return next_x, next_y return -1, -1 # 若不存在下一個(gè)空白格,則返回 -1,-1def value(m, x, y): # 返回符合'每個(gè)橫排和豎排以及九宮格內(nèi)無(wú)相同數(shù)字'這個(gè)條件的有效值。 i, j = x // 3, y // 3 grid = [m[i * 3 + r][j * 3 + c] for r in range(3) for c in range(3)] v = set([x for x in range(1, 10)]) - set(grid) - set(m[x]) - set(list(zip(*m))[y]) return list(v)def start_pos(m): # 返回第一個(gè)空白格的位置坐標(biāo) for x in range(9): for y in range(9): if m[x][y] == 0:return x, y return False, False # 若數(shù)獨(dú)已完成,則返回 False, Falsedef try_sudoku(m, x, y): # 試著填寫(xiě)數(shù)獨(dú) for v in value(m, x, y): m[x][y] = v next_x, next_y = get_next(m, x, y) if next_y == -1: # 如果無(wú)下一個(gè)空白格 return True else: end = try_sudoku(m, next_x, next_y) # 遞歸 if end:return True m[x][y] = 0 # 在遞歸的過(guò)程中,如果數(shù)獨(dú)沒(méi)有解開(kāi), # 則回溯到上一個(gè)空白格def sudoku_so(m): x, y = start_pos(m) try_sudoku(m, x, y) print('new_sudoku -> n', m) return m#################################################### 將結(jié)果繪制到原圖def draw_answer(img, contours, hierarchy, new_sudoku_list ): new_sudoku_list = new_sudoku_list .flatten().tolist() for i in range(len(contours)): cnt = contours[i] if hierarchy[0, i, -1] == 0: num = new_soduku_list.pop(-1) if hierarchy[0, i, 2] == -1:x, y, w, h = cv.boundingRect(cnt)cv.putText(img, '%d' % num, (x + 19, y + 56), cv.FONT_HERSHEY_SIMPLEX, 1.8, (0, 0, 255), 2) # 填寫(xiě)數(shù)字 cv.imwrite('E:/answer.png', img)if __name__ == ’__main__’: t1 = time.time() train_set = training() img = cv.imread(’E:/test_image/python_test_img/Sudoku.png’) img_gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY) sudoku_list, contours, hierarchy = find_dig_(img_gray, train_set) new_sudoku_list = sudoku_so(sudoku_list) draw_answer(img, contours, hierarchy, new_sudoku_list ) print('time :',time.time()-t1)

PS:

使用KNN算法需要?jiǎng)?chuàng)建訓(xùn)練集,數(shù)獨(dú)中共涉及9個(gè)數(shù)字,“1,2,3,4,5,6,7,8,9”各15幅圖放入文件夾中,如下圖所示。

Python圖像識(shí)別+KNN求解數(shù)獨(dú)的實(shí)現(xiàn)

到此這篇關(guān)于Python圖像識(shí)別+KNN求解數(shù)獨(dú)的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)Python KNN求解數(shù)獨(dú)內(nèi)容請(qǐng)搜索好吧啦網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持好吧啦網(wǎng)!

標(biāo)簽: Python 編程
相關(guān)文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
国产精品最新自拍| 欧美天堂亚洲电影院在线观看| av中文字幕在线观看第一页| 亚洲精品成人一区| 伊伊综合在线| 蜜桃久久av一区| 亚洲高清二区| 大香伊人久久精品一区二区| 日本在线精品| 久久伊人久久| 中文字幕日韩亚洲| 激情婷婷欧美| 亚洲www免费| 最新中文字幕在线播放| 狠狠久久婷婷| 久久av中文| 欧美a级片一区| 欧美午夜网站| 欧美在线精品一区| 蜜臀av一区二区在线免费观看| 国产主播一区| 久久麻豆精品| 精品三级久久| av资源中文在线| 福利精品一区| 国产aⅴ精品一区二区四区| 国产精品男女| 国产精品成人自拍| 久久一区精品| 国产传媒av在线| 色综合www| 午夜国产一区二区| 日本久久成人网| 91精品推荐| 黑丝一区二区三区| 日韩精品第二页| 鲁大师成人一区二区三区| 蜜桃91丨九色丨蝌蚪91桃色| 日韩精品91亚洲二区在线观看| 亚洲区国产区| 国产精品久久久久久av公交车| 国产精久久一区二区| 日韩免费视频| 国产日韩欧美中文在线| 欧美激情91| 999精品色在线播放| 午夜精品影视国产一区在线麻豆| 欧美一区二区三区久久精品| 欧美成人基地| 国产激情精品一区二区三区| 国产综合激情| 国产精品红桃| 亚洲日本三级| 美女少妇全过程你懂的久久| 精品国产乱码久久久| 亚洲九九精品| 色老板在线视频一区二区| 91亚洲一区| 亚洲黄页一区| 精品亚洲a∨| 国产亚洲高清视频| 国产精品成人a在线观看| 伊人精品在线| 亚洲免费专区| 国产欧美综合一区二区三区| 国产精品99一区二区| 国产亚洲人成a在线v网站| 久久青草久久| 欧美黄色一区| 精品美女视频| 成人午夜精品| 亚洲69av| 亚洲欧美日韩精品一区二区| 国产人成精品一区二区三| 日韩av二区在线播放| 97精品国产| 日本在线不卡视频| 日韩av福利| 视频一区在线视频| 精品视频网站| 性欧美69xoxoxoxo| 99精品视频在线观看免费播放| 日本久久黄色| 国产精品一级| 久久精品色播| 久久精品凹凸全集| jiujiure精品视频播放| 欧美一区网站| 亚洲激情av| 黄色av一区| 亚洲欧美日韩视频二区| 女生影院久久| 成人自拍av| 国产精品伊人| 青草综合视频| 欧美 日韩 国产一区二区在线视频 | 成人精品国产亚洲| 国产剧情一区| 国产美女久久| 91精品国产自产观看在线| 黄色亚洲大片免费在线观看| 久久xxxx| 亚洲美女91| 日韩欧美久久| 老司机精品久久| 日韩国产一区| 亚洲天堂资源| 桃色av一区二区| 国产精品原创| 伊伊综合在线| 色在线中文字幕| 国产一区2区在线观看| 日韩av福利| 欧美二三四区| 亚洲国产欧美日本视频| 美女毛片一区二区三区四区最新中文字幕亚洲| 亚洲三级网站| 国产精品一区二区av日韩在线| 国产精品色婷婷在线观看| 欧美二三四区| 中文字幕免费一区二区| 国产精品一级| 久久久蜜桃一区二区人| 日韩视频久久| 国产亚洲精品美女久久久久久久久久| 日本特黄久久久高潮| 久久久男人天堂| 一区在线观看| 精品国产欧美日韩一区二区三区| av免费不卡国产观看| 久久蜜桃精品| 日韩精品一卡| 日韩高清一区二区| 国产成人免费| 久久国产精品99国产| 亚洲精品乱码| 国产精品成人一区二区网站软件| 日韩午夜视频在线| 国产乱码午夜在线视频| 老司机久久99久久精品播放免费| 精品国产午夜肉伦伦影院| 91久久视频| 日韩一区亚洲二区| 日韩中文字幕区一区有砖一区| 久久这里只有精品一区二区| 欧美黑人做爰爽爽爽| 午夜久久美女| 国产一区二区亚洲| 亚洲精品一二三**| 久久久久久久久久久妇女| 清纯唯美亚洲综合一区| 91精品精品| 日韩av有码| 蜜臀久久99精品久久久久久9 | 久久久久久自在自线| 国产精品一区二区三区美女| 亚洲精品乱码久久久久久蜜桃麻豆| 日韩国产激情| 欧美精品影院| 日韩国产综合| 国产一区二区三区亚洲| 国产日韩一区二区三区在线| 亚洲2区在线| 中文视频一区| 一区二区国产在线| 亚洲精品国产精品粉嫩| 欧美成人久久| 欧美二区视频| 亚洲午夜免费| 日韩国产一区二| 欧美日韩亚洲三区| 日韩三级久久| 日韩极品在线观看| 国产日韩欧美一区二区三区在线观看 | 粉嫩av一区二区三区四区五区| 国产乱人伦丫前精品视频| 日韩av在线免费观看不卡| 天堂av在线一区| 91精品日本| 免费日韩一区二区三区| 激情不卡一区二区三区视频在线| 国产精品久av福利在线观看| 欧美激情福利| 亚洲小说春色综合另类电影| 午夜精品亚洲| 欧美性www| 国产a亚洲精品| 91精品国产福利在线观看麻豆| 久久不射中文字幕| 欧美日韩网址| 麻豆成全视频免费观看在线看| 国产视频一区免费看| 精品欧美视频| 奇米亚洲欧美| 欧美日韩国产探花| 日本视频一区二区| 国产精品极品在线观看| 九九久久电影| 国产欧美一区二区精品久久久| 欧美+日本+国产+在线a∨观看|