{"id":327,"date":"2021-09-19T06:53:30","date_gmt":"2021-09-18T22:53:30","guid":{"rendered":"http:\/\/blog.yuekegu.com\/?p=327"},"modified":"2021-09-19T06:53:30","modified_gmt":"2021-09-18T22:53:30","slug":"%e7%ad%94%e9%a2%98%e5%8d%a1%e8%af%86%e5%88%ab%e9%a1%b9%e7%9b%ae%e5%ae%9e%e6%88%98","status":"publish","type":"post","link":"https:\/\/book.yuekegu.com\/index.php\/2021\/09\/19\/%e7%ad%94%e9%a2%98%e5%8d%a1%e8%af%86%e5%88%ab%e9%a1%b9%e7%9b%ae%e5%ae%9e%e6%88%98\/","title":{"rendered":"\u7b54\u9898\u5361\u8bc6\u522b\u9879\u76ee\u5b9e\u6218"},"content":{"rendered":"\n<p>\u7b54\u9898\u5361\u8bc6\u522b\u6548\u679c<\/p>\n\n\n\n<p>\u5728\u8fd9\u91cc\u63d2\u5165\u56fe\u7247\u63cf\u8ff0<br>\n\u3010\u5927\u81f4\u601d\u8def\u3011\uff1a\u5148\u8fdb\u884c\u4eff\u5c04\u53d8\u6362\u53bb\u9664\u80cc\u666f\uff08\u53ea\u7559\u8bd5\u5377\u90e8\u5206\uff09\uff0c\u4e8c\u503c\u5316\uff0c\u5706\u5f62\u8f6e\u5ed3\u68c0\u6d4b\uff0c\u904d\u5386\u6bcf\u4e00\u884c\u9009\u9879\uff0c\u7edf\u8ba1\u975e\u96f6\u50cf\u7d20\uff0c\u8bb0\u5f55\u586b\u5145\u9009\u9879\uff08\u5373\u975e\u96f6\u50cf\u7d20\u6700\u591a\u7684\u8f6e\u5ed3\u533a\u57df\uff09\uff0c\u4e0e\u6b63\u786e\u7b54\u6848\u8fdb\u884c\u6bd4\u5bf9\uff0c\u6b63\u786e\u5219correct\u6570+1\uff0c\u5f97\u5230\u603b\u6210\u7ee9<br>\n1-4 \u57fa\u7840\u64cd\u4f5c+\u900f\u89c6\u53d8\u6362<\/p>\n\n\n\n<p>1-4\u662f\u57fa\u7840\u64cd\u4f5c, 3\u662f\u505a\u8fd1\u4f3c\u53d8\u6362, \u53d6\u6700\u5927\u7684\u90a3\u4e2a\u8f6e\u5ed3,\u6700\u6709\u53ef\u80fd\u662f\u56fe\u50cf\u6700\u5927\u5916\u56f4\u7684\u8f6e\u5ed3<\/p>\n\n\n\n<p>3\u7684\u8fd1\u4f3c\u53d8\u6362 \u548c 4\u7684\u900f\u89c6\u53d8\u6362\u539f\u7406 \u53ef\u4ee5\u53c2\u8003\u6211\u7684 OCR\u6587\u6863\u626b\u63cf\u5b9e\u6218<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># 1.\u9884\u5904\u7406\nimage = cv2.imread(args[\"image\"])\ncontours_img = image.copy()\ngray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)\nblurred = cv2.GaussianBlur(gray, (5, 5), 0)\ncv_show('blurred',blurred)\nedged = cv2.Canny(blurred, 75, 200)\ncv_show('edged',edged)\n\n# 2.\u8f6e\u5ed3\u68c0\u6d4b\ncnts = cv2.findContours(edged.copy(), cv2.RETR_EXTERNAL,\n\tcv2.CHAIN_APPROX_SIMPLE)[1]\ncv2.drawContours(contours_img,cnts,-1,(0,0,255),3) \ncv_show('contours_img',contours_img)\ndocCnt = None\n\n# 3.\u786e\u4fdd\u68c0\u6d4b\u5230\u4e86\nif len(cnts) > 0:\n\t# \u6839\u636e\u8f6e\u5ed3\u5927\u5c0f\u8fdb\u884c\u6392\u5e8f\n\tcnts = sorted(cnts, key=cv2.contourArea, reverse=True)\n\n\t# \u904d\u5386\u6bcf\u4e00\u4e2a\u8f6e\u5ed3\n\tfor c in cnts:\n\t\t# \u8fd1\u4f3c\n\t\tperi = cv2.arcLength(c, True)\n\t\tapprox = cv2.approxPolyDP(c, 0.02 * peri, True)\n\n\t\t# \u51c6\u5907\u505a\u900f\u89c6\u53d8\u6362\n\t\tif len(approx) == 4:\n\t\t\tdocCnt = approx\n\t\t\tbreak\n\n# 4.\u6267\u884c\u900f\u89c6\u53d8\u6362\nwarped = four_point_transform(gray, docCnt.reshape(4, 2))\ncv_show('warped',warped)\n<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/img-blog.csdnimg.cn\/20200828220354710.png?x-oss-process=image\/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3NpbmF0XzI5OTUwNzAz,size_16,color_FFFFFF,t_70#pic_center\" alt=\"\u5728\u8fd9\u91cc\u63d2\u5165\u56fe\u7247\u63cf\u8ff0\"\/><figcaption><br><\/figcaption><\/figure>\n\n\n\n<h1 class=\"wp-block-heading\">5-6 \u9608\u503c\u5904\u7406+\u8f6e\u5ed3\u68c0\u6d4b<\/h1>\n\n\n\n<p><strong>5.Otsu\u2019s \u9608\u503c\u5904\u7406<\/strong><br> THRESH_OTSU\u4f1a\u81ea\u52a8\u5bfb\u627e\u5408\u9002\u7684\u9608\u503c\uff0c\u9002\u5408\u53cc\u5cf0\uff0c\u9700\u628a\u9608\u503c\u53c2\u6570\u8bbe\u7f6e\u4e3a0<br> \u5728\u6211\u7684<a href=\"https:\/\/blog.csdn.net\/sinat_29950703\/article\/details\/107915153\">\u4fe1\u7528\u5361\u6570\u5b57\u8bc6\u522b\u6848\u4f8b<\/a>\u4e2d\u51fa\u73b0\u4e5f\u6709\u5e94\u7528(\u7b2c\u4e09\u3001\u4e94\u90e8\u5206)<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/img-blog.csdnimg.cn\/20200828221431935.png#pic_center\" alt=\"\u5728\u8fd9\u91cc\u63d2\u5165\u56fe\u7247\u63cf\u8ff0\"\/><\/figure>\n\n\n\n<p><strong>6.\u7136\u540e\u600e\u4e48\u533a\u5206\u6d82\u548c\u6ca1\u6d82\u7684\u5706\uff1f<\/strong><br> \u8fd9\u91cc\u4e0d\u7528\u970d\u592b\u53d8\u6362,\u56e0\u4e3a\u6709\u4e9b\u6d82\u5b8c\u540e \u4f1a\u7a81\u51fa\u8fb9\u754c\uff0c\u5982\u4e0b<br> <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># 5.Otsu's \u9608\u503c\u5904\u7406\nthresh = cv2.threshold(warped, 0, 255,\n\tcv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1] \ncv_show('thresh',thresh)\n\nthresh_Contours = thresh.copy()\n# 6.\u627e\u5230\u6bcf\u4e00\u4e2a\u5706\u5708\u8f6e\u5ed3\ncnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL,\n\tcv2.CHAIN_APPROX_SIMPLE)[1]\ncv2.drawContours(thresh_Contours,cnts,-1,(0,0,255),3) \ncv_show('thresh_Contours',thresh_Contours)\nquestionCnts = []\n<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/img-blog.csdnimg.cn\/20200828221232395.png?x-oss-process=image\/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3NpbmF0XzI5OTUwNzAz,size_16,color_FFFFFF,t_70#pic_center\" alt=\"\u5728\u8fd9\u91cc\u63d2\u5165\u56fe\u7247\u63cf\u8ff0\"\/><\/figure>\n\n\n\n<p>7-8 \u7b5b\u9009\u7b54\u9898\u5708<\/p>\n\n\n\n<p>7.\u904d\u5386\u6240\u6709\u5706\u5708\u8f6e\u5ed3(\u5305\u62ec\u5e72\u6270\u9879) \u7b5b\u9009\u51fa\u7b54\u9898\u533a\u57df\u7684\u5706,\u5176\u8f6e\u5ed3\u5b58\u4e8equestionCnts<br>\n\u65e0\u8bba\u662f\u5706\u5f62\u8fd8\u662f\u77e9\u5f62\u7684\u7b54\u9898\u5361,\u90fd\u662f\u89c4\u5219\u7684\u5f62\u72b6,\u6bd4\u4f8b\u76f8\u540c.<br>\n\u6240\u4ee5\u8fd9\u91cc\u8981\u4eba\u5de5\u8bbe\u5b9a\u5706\u5708\u5916\u63a5\u77e9\u5f62\u7684\u957f\u5bbd\u6bd4\u4f8b<br>\n\u53c2\u8003\u4fe1\u7528\u5361\u6570\u5b57\u8bc6\u522b (\u7b2c\u56db\u90e8\u5206)<\/p>\n\n\n\n<p>8.\u6309\u7167\u4ece\u4e0a\u5230\u4e0b(\u4ece\u5de6\u5230\u53f3)\u8fdb\u884c\u6392\u5e8f<br> \u53c2\u8003\u4fe1\u7528\u5361\u6570\u5b57\u8bc6\u522b (\u7b2c\u4e8c\u90e8\u5206)<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># 7.\u904d\u5386\u6240\u6709\u5706\u5708\u8f6e\u5ed3(\u5305\u62ec\u5e72\u6270\u9879) \u7b5b\u9009\u51fa\u7b54\u9898\u533a\u57df\u7684\u5706\nfor c in cnts:\n\t# \u8ba1\u7b97\u6bd4\u4f8b\u548c\u5927\u5c0f\n\t(x, y, w, h) = cv2.boundingRect(c)\n\tar = w \/ float(h)\n\n\t# \u6839\u636e\u5b9e\u9645\u60c5\u51b5\u6307\u5b9a\u6807\u51c6\t-- \u8fc7\u6ee4\u64cd\u4f5c\n\tif w >= 20 and h >= 20 and ar >= 0.9 and ar &lt;= 1.1:\n\t\tquestionCnts.append(c)\n\n# 8.\u6309\u7167\u4ece\u4e0a\u5230\u4e0b\u8fdb\u884c\u6392\u5e8f\nquestionCnts = sort_contours(questionCnts,\n\tmethod=\"top-to-bottom\")[0]\ncorrect = 0<\/code><\/pre>\n\n\n\n<h1 class=\"wp-block-heading\">9.\u6bcf\u884c\u76845\u4e2a\u9009\u9879 \u5206\u522b\u6bd4\u5bf9\u6b63\u786e\u7b54\u6848<\/h1>\n\n\n\n<p>\u7b54\u9898\u5708\u7684\u8f6e\u5ed3questionCnts\u957f\u5ea6\u5e94\u4e3a25, \u95f4\u96945, \u53ef\u4ee5\u904d\u53865\u6b21, \u5219<br> <strong>q \u53d60 1 2 3 4,\u51715\u884c<\/strong>;<br> <strong>i \u8868\u793a<\/strong>\u4ece\u7b2c\u51e0\u4e2a\u8f6e\u5ed3\u5f00\u59cb:0,5,10,15,20. \u5373<strong>\u6bcf\u884c\u7684\u7b2c\u4e00\u4e2a\u8f6e\u5ed3<\/strong><\/p>\n\n\n\n<h1 class=\"wp-block-heading\">9.\u6bcf\u884c\u76845\u4e2a\u9009\u9879 \u5206\u522b\u6bd4\u5bf9\u6b63\u786e\u7b54\u6848<\/h1>\n\n\n\n<p>for (q, i) in enumerate(np.arange(0, len(questionCnts), 5)):<br>\n    # 9.1\u6392\u5e8f<br>\n    cnts = sort_contours(questionCnts[i:i + 5])[0]<br>\n    bubbled = None<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># 9.2 \u904d\u5386\u6bcf\u4e00\u4e2a\u7ed3\u679c\nfor (j, c) in enumerate(cnts):\n    # 9.2.1 \u4f7f\u7528mask\u6765\u5224\u65ad\u7ed3\u679c\n    mask = np.zeros(thresh.shape, dtype=\"uint8\")\n    cv2.drawContours(mask, [c], -1, 255, -1) #-1\u8868\u793a\u586b\u5145\n    cv_show('mask',mask)\n    # 9.2.2 \u901a\u8fc7\u8ba1\u7b97\u975e\u96f6\u70b9\u6570\u91cf\u6765\u7b97\u662f\u5426\u9009\u62e9\u8fd9\u4e2a\u7b54\u6848\n    mask = cv2.bitwise_and(thresh, thresh, mask=mask)\n    total = cv2.countNonZero(mask)\n\n    # 9.2.3 \u901a\u8fc7\u9608\u503c\u5224\u65ad\n    if bubbled is None or total > bubbled[0]:\n        bubbled = (total, j)\n\n# 9.3 \u83b7\u53d6\u6b63\u786e\u7b54\u6848\ncolor = (0, 0, 255)\nk = ANSWER_KEY[q]\n\n# 9.4 \u5bf9\u6bd4\u7b54\u6848 \u5e76 \u5224\u65ad\u6b63\u786e\nif k == bubbled[1]:\n    color = (0, 255, 0)\n    correct += 1\n\n# 9.5 \u7ed8\u56fe\ncv2.drawContours(warped, [cnts[k]], -1, color, 3)<\/code><\/pre>\n\n\n\n<p>9.1 \u786e\u4fdd\u6bcf\u4e00\u884c\u7684\u987a\u5e8f\u4e3aA B C D E<br>\n9.2 \u540c\u6837\u8fd9\u4e48\u4e00\u884c\u91cc,\u8fd95\u4e2a\u6846\u6709\u4ec0\u4e48\u4e0d\u540c.<\/p>\n\n\n\n<p>j \u53d6\u6bcf\u4e2a\u9009\u98790 1 2 3 4<br>\n9.2.1 \u4f7f\u7528mask\u6765\u5224\u65ad\u7ed3\u679c<\/p>\n\n\n\n<p>\u521d\u59cb\u5316\u4e00\u4e2a \u8ddf\u900f\u89c6\u53d8\u6362\u540e\u7684\u56fe \u4e00\u6837\u5927\u5c0f\u7684mask(\u5168\u9ed1)<br>\n\u7136\u540e\u5728mask\u4e0a, \u753b\u51fa\u5f53\u524d\u904d\u5386\u7684\u8fd9\u4e2a(\u5706\u5708)\u8f6e\u5ed3c, \u753b\u6210\u767d\u8272<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>cv2.drawContours (\u4f20\u5165\u7ed8\u5236\u56fe\u50cf,\u8f6e\u5ed3,\u8f6e\u5ed3\u7d22\u5f15,\u989c\u8272\u6a21\u5f0f,\u7ebf\u6761\u539a\u5ea6)\n\u53c2\u8003OpenCV\u57fa\u672c\u64cd\u4f5c\n\u8865\u5145\u4e00\u70b9\uff1a\u7ebf\u6761\u539a\u5ea6 \u4e3a\u8d1f\u503c\u6216CV_FILLED \u8868\u793a\u586b\u5145\u8f6e\u5ed3\u5185\u90e8<\/code><\/pre>\n\n\n\n<p>\u4e00\u884c\u904d\u53865\u4e2a\u9009\u9879\uff0c5\u884c\u4e00\u517125\u4e2a\u9009\u9879\uff0c\u8fd9\u5c55\u793a\u524d\u4e24\u884c\u7684\u904d\u5386\u7ed3\u679c\uff0c\u540e\u4e09\u884c\u540c\u7406\u2026<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/img-blog.csdnimg.cn\/20200828222059710.png?x-oss-process=image\/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3NpbmF0XzI5OTUwNzAz,size_16,color_FFFFFF,t_70#pic_center\" alt=\"\u5728\u8fd9\u91cc\u63d2\u5165\u56fe\u7247\u63cf\u8ff0\"\/><\/figure>\n\n\n\n<p>9.2.2 \u4e0e\u64cd\u4f5c<\/p>\n\n\n\n<p>\u4e00\u5f20\u56fe\u7247 \u8ddf \u4e00\u5f20\u76f8\u540c\u5927\u5c0f\u7684\u9ed1\u767d\u56fe\u7247 \u8fdb\u884c\u4e0e\u64cd\u4f5c,\u5219\u53ea\u4fdd\u7559\u56fe\u7247\u7684\u767d\u8272\u533a\u57df<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>cv2.bitwise_and(src1, src2, dst=None, mask=None)\n\u5bf9\u56fe\u50cf(\u7070\u5ea6\u56fe\u50cf\u6216\u5f69\u8272\u56fe\u50cf\u5747\u53ef)\u6bcf\u4e2a\u50cf\u7d20\u503c\u8fdb\u884c\u4e8c\u8fdb\u5236\u201c\u4e0e\u201d\u64cd\u4f5c,\n1&amp;1=1\uff0c1&amp;0=0\uff0c0&amp;1=0\uff0c0&amp;0=0\n\n\u51fd\u6570\u8fd4\u56de\u503c\uff1a \u8c03\u7528\u65f6\u82e5\u65e0mask\u53c2\u6570 \u5219\u8fd4\u56desrc1 &amp; src2\uff0c\u82e5\u5b58\u5728mask\u53c2\u6570\uff0c\u5219\u8fd4\u56desrc1 &amp; src2 &amp; mask\n\n    src1\uff1a\u8f93\u5165\u539f\u56fe1\n    src2\uff1a\u8f93\u5165\u539f\u56fe2, src1\u4e0esrc2\u53ef\u4ee5\u76f8\u540c\u4e5f\u53ef\u4ee5\u4e0d\u76f8\u540c,\u53ef\u4ee5\u662f\u7070\u5ea6\u56fe\u50cf\u4e5f\u53ef\u4ee5\u662f\u5f69\u8272\u56fe\u50cf\n    dst\uff1a\u8f93\u51fa\u77e9\u9635,\u548c\u8f93\u5165\u77e9\u9635\u4e00\u6837\u7684\u5c3a\u5bf8\u548c\u7c7b\u578b \u82e5\u5b58\u5728\u53c2\u6570\u65f6\uff1asrc1 &amp; src2 \u6216\u8005 src1 &amp; src2 &amp; mask\n    mask\uff1a\u53ef\u4ee5\u662f\u5355\u901a\u90538bit\u7070\u5ea6\u56fe\u50cf,\u4e5f\u53ef\u4ee5\u662f\u77e9\u9635,\u4e00\u822c\u4e3a\u4e8c\u503c\u5316\u540e\u7684\u56fe\u50cf,\u6307\u5b9a\u8981\u66f4\u6539\u7684\u8f93\u51fa\u6570\u7ec4\u7684\u5143\u7d20\n\ncv2.countNonZero\u7edf\u8ba1\u975e\u96f6\u50cf\u7d20\u70b9\u4e2a\u6570<\/code><\/pre>\n\n\n\n<p>9.2.3 \u4f9d\u6b21\u5224\u65ad5\u4e2a\u9009\u9879\u7684\u54ea\u4e2a\u975e\u96f6\u503c\u6700\u5927(\u5373\u54ea\u4e2a\u88ab\u586b\u5145\u4e0a\u4e86)<\/p>\n\n\n\n<p>total &gt; bubbled[0] \u6bd4\u5b83\u5927\u7684\u624d\u4fdd\u7559\u5230bubbled<br>\nbubbled \u4fdd\u7559\u6700\u5927\u7684\u9009\u9879( \u5373\u586b\u5145\u4e0a\u7684\u9009\u9879 ) j<br>\n9.3 k = ANSWER_KEY[q] \u662f\u7b2c\u51e0\u9898(\u884c)\u7684\u6b63\u786e\u7b54\u6848<br>\n9.4 \u82e5k = bubbled[1]\uff0c\u5224\u65ad\u6b63\u786e\uff0ccorrect+=1<\/p>\n\n\n\n<p>.<br> 10.\u6253\u5370\u6b63\u786e\u7387<br><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># 10.\u6253\u5370\u6b63\u786e\u7387\nscore = (correct \/ 5.0) * 100\nprint(\"[INFO] score: {:.2f}\ncv2.putText(warped, \"{:.2f}\n\tcv2.FONT_HERSHEY_SIMPLEX, 0.9, (0, 255, 0), 2)\ncv2.imshow(\"Original\", image)\ncv2.imshow(\"Exam\", warped)\ncv2.waitKey(0)<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/img-blog.csdnimg.cn\/20200828224142958.png?x-oss-process=image\/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3NpbmF0XzI5OTUwNzAz,size_16,color_FFFFFF,t_70#pic_center\" alt=\"\u5728\u8fd9\u91cc\u63d2\u5165\u56fe\u7247\u63cf\u8ff0\"\/><\/figure>\n\n\n\n<h1 class=\"wp-block-heading\">* \u6d4b\u8bd5\u5176\u4ed6\u7b54\u9898\u5361\u6548\u679c<\/h1>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/img-blog.csdnimg.cn\/20200828225031606.png?x-oss-process=image\/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3NpbmF0XzI5OTUwNzAz,size_16,color_FFFFFF,t_70#pic_center\" alt=\"\u5728\u8fd9\u91cc\u63d2\u5165\u56fe\u7247\u63cf\u8ff0\"\/><\/figure>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/img-blog.csdnimg.cn\/20200828225031720.png?x-oss-process=image\/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3NpbmF0XzI5OTUwNzAz,size_16,color_FFFFFF,t_70#pic_center\" alt=\"\u5728\u8fd9\u91cc\u63d2\u5165\u56fe\u7247\u63cf\u8ff0\"\/><\/figure>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/img-blog.csdnimg.cn\/20200828225031620.png?x-oss-process=image\/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3NpbmF0XzI5OTUwNzAz,size_16,color_FFFFFF,t_70#pic_center\" alt=\"\u5728\u8fd9\u91cc\u63d2\u5165\u56fe\u7247\u63cf\u8ff0\"\/><\/figure>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/img-blog.csdnimg.cn\/20200828225031500.png?x-oss-process=image\/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3NpbmF0XzI5OTUwNzAz,size_16,color_FFFFFF,t_70#pic_center\" alt=\"\u5728\u8fd9\u91cc\u63d2\u5165\u56fe\u7247\u63cf\u8ff0\"\/><\/figure>\n\n\n\n<h1 class=\"wp-block-heading\">\u7ed3\u675f\u8bed<\/h1>\n\n\n\n<p>\u867d\u7136\u4ee3\u7801\u6709\u70b9\u957f\uff0c\u4f46\u5927\u90e8\u5206\u5185\u5bb9\u90fd\u662f\u524d\u9762\u51e0\u4e2a\u9879\u76ee\u6709\u7528\u5230\u7684\u77e5\u8bc6\u3002\u53ef\u89c1\u9047\u5230\u4e0d\u540c\u573a\u666f\u7684\u4e3e\u4e00\u53cd\u4e09\u80fd\u529b\u591a\u91cd\u8981\u5566<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">\u6269\u5c55<\/h1>\n\n\n\n<p>\u6709\u5174\u8da3\u7684\u540c\u5b66\u4eec \u53ef\u4ee5\u5c1d\u8bd5\u4e00\u4e0b<strong>\u77e9\u5f62\u7b54\u9898\u5361<\/strong>\u7684\u8bc6\u522b<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">\u5b8c\u6574\u4ee3\u7801<\/h1>\n\n\n\n<p>\u4e00\u4e2apy\u6587\u4ef6\uff0c3\u4e2a\u51fd\u6570<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># \u5bfc\u5165\u5de5\u5177\u5305\nimport numpy as np\nimport argparse\nimport cv2\ndef order_points(pts):\n\t# \u4e00\u51714\u4e2a\u5750\u6807\u70b9\n\trect = np.zeros((4, 2), dtype = \"float32\")\n\n\t# \u6309\u987a\u5e8f\u627e\u5230\u5bf9\u5e94\u5750\u68070123\u5206\u522b\u662f \u5de6\u4e0a\uff0c\u53f3\u4e0a\uff0c\u53f3\u4e0b\uff0c\u5de6\u4e0b\n\t# \u8ba1\u7b97\u5de6\u4e0a\uff0c\u53f3\u4e0b\n\ts = pts.sum(axis = 1)\n\trect[0] = pts[np.argmin(s)]\n\trect[2] = pts[np.argmax(s)]\n\n\t# \u8ba1\u7b97\u53f3\u4e0a\u548c\u5de6\u4e0b\n\tdiff = np.diff(pts, axis = 1)\n\trect[1] = pts[np.argmin(diff)]\n\trect[3] = pts[np.argmax(diff)]\n\n\treturn rect\n\ndef four_point_transform(image, pts):\n\t# \u83b7\u53d6\u8f93\u5165\u5750\u6807\u70b9\n\trect = order_points(pts)\n\t(tl, tr, br, bl) = rect\n\n\t# \u8ba1\u7b97\u8f93\u5165\u7684w\u548ch\u503c\n\twidthA = np.sqrt(((br[0] - bl[0]) ** 2) + ((br[1] - bl[1]) ** 2))\n\twidthB = np.sqrt(((tr[0] - tl[0]) ** 2) + ((tr[1] - tl[1]) ** 2))\n\tmaxWidth = max(int(widthA), int(widthB))\n\n\theightA = np.sqrt(((tr[0] - br[0]) ** 2) + ((tr[1] - br[1]) ** 2))\n\theightB = np.sqrt(((tl[0] - bl[0]) ** 2) + ((tl[1] - bl[1]) ** 2))\n\tmaxHeight = max(int(heightA), int(heightB))\n\n\t# \u53d8\u6362\u540e\u5bf9\u5e94\u5750\u6807\u4f4d\u7f6e\n\tdst = np.array([\n\t\t[0, 0],\n\t\t[maxWidth - 1, 0],\n\t\t[maxWidth - 1, maxHeight - 1],\n\t\t[0, maxHeight - 1]], dtype = \"float32\")\n\n\t# \u8ba1\u7b97\u53d8\u6362\u77e9\u9635\n\tM = cv2.getPerspectiveTransform(rect, dst)\n\twarped = cv2.warpPerspective(image, M, (maxWidth, maxHeight))\n\n\t# \u8fd4\u56de\u53d8\u6362\u540e\u7ed3\u679c\n\treturn warped\ndef sort_contours(cnts, method=\"left-to-right\"):\n    reverse = False\n    i = 0\n    if method == \"right-to-left\" or method == \"bottom-to-top\":\n        reverse = True\n    if method == \"top-to-bottom\" or method == \"bottom-to-top\":\n        i = 1\n    boundingBoxes = [cv2.boundingRect(c) for c in cnts]\n    (cnts, boundingBoxes) = zip(*sorted(zip(cnts, boundingBoxes),\n                                        key=lambda b: b[1][i], reverse=reverse))\n    return cnts, boundingBoxes\ndef cv_show(name,img):\n    cv2.imshow(name, img)\n    cv2.waitKey(0)\n    cv2.destroyAllWindows()  \n\n'''\u4e0b\u9762\u4e3a\u4e3b\u51fd\u6570'''\nif __name__ == \"__main__\":\n\t# \u8bbe\u7f6e\u53c2\u6570\n\tap = argparse.ArgumentParser()\n\tap.add_argument(\"-i\", \"--image\", required=True,\n\t\thelp=\"path to the input image\")\n\targs = vars(ap.parse_args())\n\n\t# \u6b63\u786e\u7b54\u6848\n\tANSWER_KEY = {0: 1, 1: 4, 2: 0, 3: 3, 4: 1}\n\n\t# 1.\u9884\u5904\u7406\n\timage = cv2.imread(args[\"image\"])\n\tcontours_img = image.copy()\n\tgray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)\n\tblurred = cv2.GaussianBlur(gray, (5, 5), 0)\n\tcv_show('blurred',blurred)\n\tedged = cv2.Canny(blurred, 75, 200)\n\tcv_show('edged',edged)\n\n\t# 2.\u8f6e\u5ed3\u68c0\u6d4b\n\tcnts = cv2.findContours(edged.copy(), cv2.RETR_EXTERNAL,\n\t\tcv2.CHAIN_APPROX_SIMPLE)[1]\n\tcv2.drawContours(contours_img,cnts,-1,(0,0,255),3) \n\tcv_show('contours_img',contours_img)\n\tdocCnt = None\n\n\t# 3.\u786e\u4fdd\u68c0\u6d4b\u5230\u4e86\n\tif len(cnts) > 0:\n\t\t# \u6839\u636e\u8f6e\u5ed3\u5927\u5c0f\u8fdb\u884c\u6392\u5e8f\n\t\tcnts = sorted(cnts, key=cv2.contourArea, reverse=True)\n\n\t\t# \u904d\u5386\u6bcf\u4e00\u4e2a\u8f6e\u5ed3\n\t\tfor c in cnts:\n\t\t\t# \u8fd1\u4f3c\n\t\t\tperi = cv2.arcLength(c, True)\n\t\t\tapprox = cv2.approxPolyDP(c, 0.02 * peri, True)\n\n\t\t\t# \u51c6\u5907\u505a\u900f\u89c6\u53d8\u6362\n\t\t\tif len(approx) == 4:\n\t\t\t\tdocCnt = approx\n\t\t\t\tbreak\n\n\t# 4.\u6267\u884c\u900f\u89c6\u53d8\u6362\n\twarped = four_point_transform(gray, docCnt.reshape(4, 2))\n\tcv_show('warped',warped)\n\t# 5.Otsu's \u9608\u503c\u5904\u7406\n\tthresh = cv2.threshold(warped, 0, 255,\n\t\tcv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1] \n\tcv_show('thresh',thresh)\n\n\tthresh_Contours = thresh.copy()\n\t# 6.\u627e\u5230\u6240\u6709\u8f6e\u5ed3\n\tcnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL,\n\t\tcv2.CHAIN_APPROX_SIMPLE)[1]\n\tcv2.drawContours(thresh_Contours,cnts,-1,(0,0,255),3) \n\tcv_show('thresh_Contours',thresh_Contours)\n\tquestionCnts = []\n\n\t# 7.\u904d\u5386\u6240\u6709\u5706\u5708\u8f6e\u5ed3(\u5305\u62ec\u5e72\u6270\u9879) \u7b5b\u9009\u51fa\u7b54\u9898\u533a\u57df\u7684\u5706\n\tfor c in cnts:\n\t\t# \u8ba1\u7b97\u6bd4\u4f8b\u548c\u5927\u5c0f\n\t\t(x, y, w, h) = cv2.boundingRect(c)\n\t\tar = w \/ float(h)\n\n\t\t# \u6839\u636e\u5b9e\u9645\u60c5\u51b5\u6307\u5b9a\u6807\u51c6\t-- \u8fc7\u6ee4\u64cd\u4f5c\n\t\tif w >= 20 and h >= 20 and ar >= 0.9 and ar &lt;= 1.1:\n\t\t\tquestionCnts.append(c)\n\n\t# 8.\u6309\u7167\u4ece\u4e0a\u5230\u4e0b\u8fdb\u884c\u6392\u5e8f\n\tquestionCnts = sort_contours(questionCnts,\n\t\tmethod=\"top-to-bottom\")[0]\n\tcorrect = 0\n\n\t# 9.\u6bcf\u884c\u76845\u4e2a\u9009\u9879 \u5206\u522b\u6bd4\u5bf9\u6b63\u786e\u7b54\u6848\n\tfor (q, i) in enumerate(np.arange(0, len(questionCnts), 5)):\n\t\t# 9.1\u6392\u5e8f\n\t\tcnts = sort_contours(questionCnts[i:i + 5])[0]\n\t\tbubbled = None\n\n\t\t# 9.2 \u904d\u5386\u6bcf\u4e00\u4e2a\u7ed3\u679c\n\t\tfor (j, c) in enumerate(cnts):\n\t\t\t# 9.2.1 \u4f7f\u7528mask\u6765\u5224\u65ad\u7ed3\u679c\n\t\t\tmask = np.zeros(thresh.shape, dtype=\"uint8\")\n\t\t\tcv2.drawContours(mask, [c], -1, 255, -1) #-1\u8868\u793a\u586b\u5145\n\t\t\t# cv_show('mask',mask)\n\t\t\t# 9.2.2 \u901a\u8fc7\u8ba1\u7b97\u975e\u96f6\u70b9\u6570\u91cf\u6765\u7b97\u662f\u5426\u9009\u62e9\u8fd9\u4e2a\u7b54\u6848\n\t\t\tmask = cv2.bitwise_and(thresh, thresh, mask=mask)\n\t\t\ttotal = cv2.countNonZero(mask)\n\n\t\t\t# 9.2.3 \u901a\u8fc7\u9608\u503c\u5224\u65ad\n\t\t\tif bubbled is None or total > bubbled[0]:\n\t\t\t\tbubbled = (total, j)\n\n\t\t# 9.3 \u83b7\u53d6\u6b63\u786e\u7b54\u6848\n\t\tcolor = (0, 0, 255)\n\t\tk = ANSWER_KEY[q]\n\n\t\t# 9.4 \u5bf9\u6bd4\u7b54\u6848 \u5e76 \u5224\u65ad\u6b63\u786e\n\t\tif k == bubbled[1]:\n\t\t\tcolor = (0, 255, 0)\n\t\t\tcorrect += 1\n\n\t\t# 9.5 \u7ed8\u56fe\n\t\tcv2.drawContours(warped, [cnts[k]], -1, color, 3)\n\n\t# 10.\u6253\u5370\u6b63\u786e\u7387\n\tscore = (correct \/ 5.0) * 100\n\tprint(\"[INFO] score: {:.2f}\n\tcv2.putText(warped, \"{:.2f}\n\t\tcv2.FONT_HERSHEY_SIMPLEX, 0.9, (0, 255, 0), 2)\n\tcv2.imshow(\"Original\", image)\n\tcv2.imshow(\"Exam\", warped)\n\tcv2.waitKey(0)\n\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\u2014\n\u7248\u6743\u58f0\u660e\uff1a\u672c\u6587\u4e3aCSDN\u535a\u4e3b\u300c\u9f99\u5171\u65e5\u5c27\u300d\u7684\u539f\u521b\u6587\u7ae0\uff0c\u9075\u5faaCC 4.0 BY-SA\u7248\u6743\u534f\u8bae\uff0c\u8f6c\u8f7d\u8bf7\u9644\u4e0a\u539f\u6587\u51fa\u5904\u94fe\u63a5\u53ca\u672c\u58f0\u660e\u3002\n\u539f\u6587\u94fe\u63a5\uff1ahttps:\/\/blog.csdn.net\/sinat_29950703\/article\/details\/108287249<\/code><\/pre>\n\n\n\n<p>\u76f8\u5173\u6587\u7ae0\u6536\u85cf\uff1a<\/p>\n\n\n\n<p><a href=\"https:\/\/blog.csdn.net\/z649431508\/article\/details\/77905963?utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Edefault-6.no_search_link&amp;depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Edefault-6.no_search_link\">\u5229\u7528Python+opencv+TensorFlow\u6846\u67b6\u6253\u9020 \u4e00\u4e2a\u8bd5\u5377\u6279\u6539\u7cfb\u7edf<\/a> <\/p>\n\n\n\n<p><a href=\"https:\/\/download.csdn.net\/download\/La_vie_est_belle\/18371132?utm_medium=distribute.pc_relevant_download.none-task-download-2~default~OPENSEARCH~default-1.test_version_3&amp;depth_1-utm_source=distribute.pc_relevant_download.none-task-download-2~default~OPENSEARCH~default-1.test_version_3&amp;dest=https%3A%2F%2Fdownload.csdn.net%2Fdownload%2FLa_vie_est_belle%2F18371132\">Python+OpenCV+PyQt\u5f00\u53d1\u7b54\u9898\u5361\u8bc6\u522b\u8f6f\u4ef6\u6e90\u7801 <\/a><\/p>\n\n\n\n<p> <strong><a rel=\"noreferrer noopener\" href=\"https:\/\/blog.csdn.net\/a1111111111ss\/article\/details\/106056217\" target=\"_blank\">\u8ba1\u7b97\u673a\u89c6\u89c9OpenCV\u7b54\u9898\u5361\u8bc6\u522b\u9879\u76ee\u5b9e\u6218<\/a><\/strong> <\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u7b54\u9898\u5361\u8bc6\u522b\u6548\u679c \u5728\u8fd9\u91cc\u63d2\u5165\u56fe\u7247\u63cf\u8ff0 \u3010\u5927\u81f4\u601d\u8def\u3011\uff1a\u5148\u8fdb\u884c\u4eff\u5c04\u53d8\u6362\u53bb\u9664\u80cc\u666f\uff08\u53ea\u7559\u8bd5\u5377\u90e8\u5206\uff09\uff0c\u4e8c\u503c\u5316\uff0c\u5706\u5f62\u8f6e\u5ed3\u68c0\u6d4b\uff0c\u904d\u5386\u6bcf\u4e00\u884c\u9009\u9879\uff0c\u7edf\u8ba1\u975e\u96f6\u50cf\u7d20\uff0c\u8bb0\u5f55\u586b\u5145\u9009\u9879\uff08\u5373\u975e\u96f6\u50cf\u7d20\u6700\u591a\u7684\u8f6e\u5ed3\u533a\u57df\uff09\uff0c\u4e0e\u6b63\u786e\u7b54\u6848\u8fdb\u884c\u6bd4\u5bf9\uff0c\u6b63\u786e\u5219correct\u6570+1\uff0c\u5f97\u5230\u603b\u6210\u7ee9 1-4 \u57fa\u7840\u64cd\u4f5c+\u900f\u89c6\u53d8\u6362 1-4\u662f\u57fa\u7840\u64cd\u4f5c, 3\u662f\u505a\u8fd1\u4f3c\u53d8\u6362, \u53d6\u6700\u5927\u7684\u90a3\u4e2a\u8f6e\u5ed3,\u6700\u6709\u53ef\u80fd\u662f\u56fe\u50cf\u6700\u5927\u5916\u56f4\u7684\u8f6e\u5ed3 3\u7684\u8fd1\u4f3c\u53d8\u6362 \u548c 4\u7684\u900f\u89c6\u53d8\u6362\u539f\u7406 \u53ef\u4ee5\u53c2\u8003\u6211\u7684 OCR\u6587\u6863\u626b\u63cf\u5b9e\u6218 5-6 \u9608\u503c\u5904\u7406+\u8f6e\u5ed3\u68c0\u6d4b 5.Otsu\u2019s \u9608\u503c\u5904\u7406 THRESH_OTSU\u4f1a\u81ea\u52a8\u5bfb\u627e\u5408\u9002\u7684\u9608\u503c\uff0c\u9002\u5408\u53cc\u5cf0\uff0c\u9700\u628a\u9608\u503c\u53c2\u6570\u8bbe\u7f6e\u4e3a0 \u5728\u6211\u7684\u4fe1\u7528\u5361\u6570\u5b57\u8bc6\u522b\u6848\u4f8b\u4e2d\u51fa\u73b0\u4e5f\u6709\u5e94\u7528(\u7b2c\u4e09\u3001\u4e94\u90e8\u5206) 6.\u7136\u540e\u600e\u4e48\u533a\u5206\u6d82\u548c\u6ca1\u6d82\u7684\u5706\uff1f \u8fd9\u91cc\u4e0d\u7528\u970d\u592b\u53d8\u6362,\u56e0\u4e3a\u6709\u4e9b\u6d82\u5b8c\u540e \u4f1a\u7a81\u51fa\u8fb9\u754c\uff0c\u5982\u4e0b 7-8 \u7b5b\u9009\u7b54\u9898\u5708 7.\u904d\u5386\u6240\u6709\u5706\u5708\u8f6e\u5ed3(\u5305\u62ec\u5e72\u6270\u9879) \u7b5b\u9009\u51fa\u7b54\u9898\u533a\u57df\u7684\u5706,\u5176\u8f6e\u5ed3\u5b58\u4e8equestionCnts \u65e0\u8bba\u662f\u5706\u5f62\u8fd8\u662f\u77e9\u5f62\u7684\u7b54\u9898\u5361,\u90fd\u662f\u89c4\u5219\u7684\u5f62\u72b6,\u6bd4\u4f8b\u76f8\u540c. \u6240\u4ee5\u8fd9\u91cc\u8981\u4eba\u5de5\u8bbe\u5b9a\u5706\u5708\u5916\u63a5\u77e9\u5f62\u7684\u957f\u5bbd\u6bd4\u4f8b \u53c2\u8003\u4fe1\u7528\u5361\u6570\u5b57\u8bc6\u522b (\u7b2c\u56db\u90e8\u5206) 8.\u6309\u7167\u4ece\u4e0a\u5230\u4e0b(\u4ece\u5de6\u5230\u53f3)\u8fdb\u884c\u6392\u5e8f \u53c2\u8003\u4fe1\u7528\u5361\u6570\u5b57\u8bc6\u522b (\u7b2c\u4e8c\u90e8\u5206) 9.\u6bcf\u884c\u76845\u4e2a\u9009\u9879 \u5206\u522b\u6bd4\u5bf9\u6b63\u786e\u7b54\u6848 \u7b54\u9898\u5708\u7684\u8f6e\u5ed3questionCnts\u957f\u5ea6\u5e94\u4e3a25, \u95f4\u96945, \u53ef\u4ee5\u904d\u53865\u6b21, \u5219 q \u53d60 1 [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[13],"tags":[],"class_list":["post-327","post","type-post","status-publish","format-standard","hentry","category-python"],"_links":{"self":[{"href":"https:\/\/book.yuekegu.com\/index.php\/wp-json\/wp\/v2\/posts\/327","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/book.yuekegu.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/book.yuekegu.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/book.yuekegu.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/book.yuekegu.com\/index.php\/wp-json\/wp\/v2\/comments?post=327"}],"version-history":[{"count":0,"href":"https:\/\/book.yuekegu.com\/index.php\/wp-json\/wp\/v2\/posts\/327\/revisions"}],"wp:attachment":[{"href":"https:\/\/book.yuekegu.com\/index.php\/wp-json\/wp\/v2\/media?parent=327"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/book.yuekegu.com\/index.php\/wp-json\/wp\/v2\/categories?post=327"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/book.yuekegu.com\/index.php\/wp-json\/wp\/v2\/tags?post=327"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}