明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 4956|回复: 27

[源码] ocr图片识别研究

  [复制链接]
发表于 2023-6-10 08:53:10 | 显示全部楼层 |阅读模式
购买主题 已有 17 人购买  本主题需向作者支付 3 个明经币 才能浏览
"觉得好,就打赏"
还没有人打赏,支持一下
发表于 2023-6-10 11:32:58 | 显示全部楼层
dhl 发表于 2023-6-10 10:14
我win10上找不到OCR.EXE

可以试试这个,https://github.com/zh-h/Windows.Media.Ocr.Cli


.net v4.5.1
WIN10版本要求
Build 10240, Build 10586, Build 14383, Build 15063, Build 16299, Build 17134, Build 17763, Build 18362, Build 19041, Build 20348, Build 22000, Build 22621

说明
===========================================================================================
Windows.Media.Ocr.Cli
Ocr 命令行工具, 本地调用 UWP API Windows.Media.Ocr 支持多种语言识别。

使用
下载
https://github.com/zh-h/Windows.Media.Ocr.Cli/releases

命令行执行
PS C:\Tools>Windows.Media.Ocr.Cli.exe .\x.png
9·哪位科学家发现了电磁感应现象?
PS C:\Tools>Windows.Media.Ocr.Cli.exe -o .\res.txt .\x.png
-> 将内容输出到res.txt中
查看帮助
PS C:\Tools>Windows.Media.Ocr.Cli.exe -h
Usage: Windows.Media.Ocr.Cli.exe [options...] <image file path>
Example: Windows.Media.Ocr.Cli.exe -o c:\res.txt x.png
-l      <language>  Default:zh-Hans-CN   Specify language to reconizing
-o      <output_path> Output the resalut to a file, It should end with a file name, such as res.txt.
-s      Show all supported languages
-h      Show help like this
运行依赖
需要 Windows 10 系统,其他平台没有测试,理论上可以支持所有支持 UWP 的设备,包括 Xbox 甚至安装 Windows 10 IoT 的树莓派,不太了解 Xamarin 能不能引入 UWP 的 runtime,如果能引入 UWP 就可以用在 iOS 和 Android 平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

x

评分

参与人数 1明经币 +1 收起 理由
Bao_lai + 1 很给力!

查看全部评分

回复 支持 1 反对 0

使用道具 举报

发表于 2024-5-12 16:35:07 | 显示全部楼层
;(setq qz (vl-filename-mktemp "ocr" (getvar "SAVEFILEPATH")) ) ;前缀(vl-filename-mktemp "ocr" (getenv "temp"))

临时文件放临时保存文件夹较为合适,WIN10某些C盘不能读入写出文件,很烦,(getvar "SAVEFILEPATH") 保存到D盘
  OCR不认文件路径"\\",只是认识 正斜杠 于是又要替换 ljx-string-translate
  OCR放在CAD安装目录,反正又不大,,不用写路径直接如:(command "shell" Windows.Media.Ocr.Cli.exe  d:/temp/ocr004.png > d:/temp/ocr004.txt )
Windows.Media.Ocr.Cli.exe要把断线文字线条加宽,不然不认识,空却,还经常认错字,像我一样近视,不要抱太大期望

  1. ;;;;函数名称:  ljx-string-translate
  2. ;;;;调用格式:  (ljx-string-translate newtx oldtx str)
  3. ;;;;参数说明:  newtx ----- 要替换成的新字符
  4. ;;;;            oldtx-要替换的旧字符
  5. ;;;;            str  在str字符中替换      
  6. ;;;;返回值:  (ljx-string-translate "xx" "a" "123xxjkhxx") 返回""123ajkha""、
  7. ;;;;            (ljx-string-translate "xx" "" "123jkh")返回"1213jkh"
  8. ;;;;            newtx为""时相当于删除字符功能,非常好用
  9. ;;;;函数简介:  字符串替换函数,要替换的源字符与新字符长度可以不同,替换非常灵活好用            
  10. ;;;;函数来源:  原创
  11. ;;;;函数作者:  jixiangluo
  12. ;;;;适用版本:  不限
  13. ;;;;最后更新时  2019-08-03

  14. ;|(defun ljx-string-translate (newtx oldtx str / str1 i txz txy)
  15.   (setq str1 str)
  16.   (while (vl-string-search oldtx str1 )
  17.     (cond
  18.       ((= oldtx str1)
  19.        (setq str newtx)
  20.       )
  21.       ((= (vl-string-search oldtx str1) 0)
  22.        (setq i (+ (strlen oldtx) 1)
  23.        txy""
  24.        )
  25.        (repeat (- (strlen str1) (strlen oldtx))
  26.    (setq txy (strcat txy (substr str1 i 1))
  27.          i (1+ i)
  28.    )
  29.        );;;;repeat
  30.        (setq str (strcat newtx txy))
  31.       )
  32.       ((= (vl-string-search oldtx str1) (- (strlen str1) (strlen oldtx) 1))
  33.        (setq i 1
  34.        txz ""
  35.        )
  36.        (repeat (- (strlen str1) (strlen oldtx))
  37.    (setq txz (strcat txz (substr str1 i 1))
  38.          i (1+ i)
  39.    )
  40.        )
  41.        (setq str (strcat txz newtx))
  42.       )
  43.       (T
  44.        (setq i 1
  45.              txz ""
  46.        )
  47.        (repeat (vl-string-search oldtx str1)
  48.    (setq txz (strcat txz (substr str1 i 1))
  49.          i (1+ i)
  50.    )
  51.        );;;;repeat
  52.        (setq i (+ i (strlen oldtx))
  53.        txy ""
  54.        )
  55.        (repeat (- (strlen str1) i -1)
  56.    (setq txy (strcat txy (substr str1 i 1))
  57.          i (1+ i)
  58.          )
  59.        );;;;repeat
  60.        (setq str (strcat txz newtx txy))
  61.       )
  62.     );;;;cond
  63.     (setq str1 str)
  64.   );;;;while
  65.   str1
  66. );;;;defun|;

  67. (defun ljx-string-translate (newtx oldtx str / str1 strL oldL txt tx1 tx2 n1)
  68.   (setq str1 str
  69.   strL (strlen str1)
  70.   oldL (strlen oldtx)
  71.   txt ""
  72.   )
  73.   (while (setq n1 (vl-string-search oldtx str1 ))
  74.     (setq tx1 (substr str1 1 n1)
  75.     tx2 (substr str1 (+ n1 1 oldL) (- strL (strlen tx1) oldL))
  76.     txt (strcat txt tx1 newtx)
  77.     )
  78.     (setq str1 tx2
  79.     strL (strlen str1)
  80.     )
  81.   )
  82.   (setq txt (strcat txt str1))
  83. );;;;defun






  84. (defun lst->ss (lst / SS X)
  85.   ;图元转选择集
  86.   (if (and lst (setq lst (vl-remove nil lst))(setq
  87.          lst (VL-REMOVE-IF-NOT (FUNCTION (LAMBDA (A) (ENTGET A))) lst)
  88.        ))
  89.     (progn
  90.       (setq ss (ssadd))
  91.       (last
  92.     (mapcar(function(lambda (x) (ssadd x ss)))lst)
  93.       )
  94.     )
  95.   )
  96.   SS
  97. )

  98. (defun $ocr-dwg$ (ss  )
  99.   (setq qz (vl-filename-mktemp "ocr" (getvar "SAVEFILEPATH")) ) ;前缀(vl-filename-mktemp "ocr" (getenv "temp"))
  100.   (setq png-p (strcat qz ".png"))  ;图片文件名
  101.   (setq txt-p (strcat qz ".txt"))  ;txt文件名
  102.   ;(setq ss  (ssget ) )      ;提示用户框选pdf图元  SS在主函数中"_P"
  103.   (VL-CMDF "PNGOUT" png-p ss "") ;输出图片

  104.   (SETQ EXE-P (findfile "Windows.Media.Ocr.Cli.exe"))
  105. (vl-cmdf "shell" (strcat  "Windows.Media.Ocr.Cli.exe"  " " (ljx-string-translate "/" "\\" png-p) " " " > " (ljx-string-translate "/" "\\" txt-p) ))
  106.   
  107.   
  108.   
  109.   
  110.   (setq i 0)
  111.   (setq go t)
  112.   (while (and go (< i 200000000))  ;防止ocr软件保存txt时间不够,这里给定循环时间
  113.     (if (setq f (vl-catch-all-apply 'open (list txt-p "r")))
  114.           ;开启txt文件准备读取字串
  115.       (while
  116.         (setq str (vl-catch-all-apply 'read-line (list f)))
  117.           ;逐行读取
  118.          (if str
  119.      (setq go nil)
  120.          )      ;一旦读取到了字串就让while结束循环
  121.          (setq strs (cons str strs)) ;字串记录
  122.       )
  123.     )
  124.     (vl-catch-all-apply 'close (list f)) ;关闭文件
  125.     (setq i (1+ i))
  126.   )
  127.   (setq strs (vl-remove '"" strs)) ;删除空行
  128.   (setq strs (reverse strs))  ;颠倒过来
  129.       
  130.    
  131.   
  132.   (and ss(setq ents(vl-remove-if(function listp)(mapcar (function cadr) (ssnamex SS)))));选择集转图元
  133.   (setq jbs(mapcar(function(lambda(a)(cdr(assoc 5(entget a)))))ents));获取句柄
  134.   (if ss(SETQ BOX (getbox SS NIL)))
  135.   (vl-catch-all-apply 'vl-file-delete (list png-p)) ;删除图片文件
  136.   (vl-catch-all-apply 'vl-file-delete (list txt-p)) ;删除txt文件
  137.   (setq ss nil)
  138.   (LIST (CONS "坐标" BOX) (cons "字串" strs)(cons "图元句柄" jbs));返回
  139. )

  140. (defun getbox (xzj         QJBLM           /             i               xdir
  141.                ydir         zdir           origin    wcsOrg    UcsFlag
  142.                matLst         matrix           revMat    sel       ent
  143.                obj         minPt           maxPt     minLs     maxLs
  144.                maxX         maxY           minX             minY
  145.                Make-Rectange-getbox             dxf $GetMatrix$
  146.               )
  147. ;;; ;诡异的填充
  148.                                         ;(ENTMAKE (QUOTE ((0 . HATCH) (100 . AcDbEntity) (100 . AcDbHatch) (10 0.0 0.0 0.0) (210 0.0 0.0 1.0) (2 . SOLID) (70 . 1) (71 . 0) (91 . 1) (92 . 1) (93 . 1) (72 . 2) (10 3.67321e-006 -1.0 0.0) (40 . 1.0) (50 . 1.5708) (51 . 1.5708) (73 . 1) (97 . 0) (75 . 0) (76 . 1) (98 . 1) (10 97.2 305.1 0.0))))会导致外包围错误
  149.   ;;先判断UCS是否与WCS相同。如是则取得UCS的X方向,
  150.   ;;Y方向,Z方向,UCS原点及WCS的原点相对UCS的坐标点
  151.   ;;然后得到UCS变换矩阵和到WCS的逆变换矩阵
  152.                                         ;QJBLM  全局使用的变量名(字符串格式),这个将作为全局变量名供很多地方调用
  153.   (defun Make-Rectange-getbox (PTT1 PTT2 QJBLM)
  154. ;;;    ;构造矩形
  155. ;;;    (IF (/= $EF-tzqy(vl-princ-to-string(list(list (car PTT1) (cadr PTT1))(list (car PTT2) (cadr PTT1))(list (car PTT2) (cadr PTT2))(list (car PTT1) (cadr PTT2)))))(ALERT "变了哦"))
  156.     (set (read QJBLM)
  157.          (vl-princ-to-string
  158.            (list (list (car PTT1) (cadr PTT1))
  159.                  (list (car PTT2) (cadr PTT1))
  160.                  (list (car PTT2) (cadr PTT2))
  161.                  (list (car PTT1) (cadr PTT2))
  162.            )
  163.          )                                ;将坐标点赋值给QJBLM
  164.     )
  165. ;;;  (TTEDIT (entlast) "zx-tzqy" (cons 1000 (vl-princ-to-string(list(list (car PTT1) (cadr PTT1))(list (car PTT2) (cadr PTT1))(list (car PTT2) (cadr PTT2))(list (car PTT1) (cadr PTT2))))) "del")
  166.   )
  167.   (defun $GetMatrix$ (lst org Revflag / mat i j)
  168.   (setq mat (vlax-make-safearray vlax-vbDouble '(0 . 3) '(0 . 3)))
  169.                                         ;初始化一个4X4的矩阵
  170.   (setq i 0)
  171.   (repeat 3
  172.     (vlax-safearray-put-element mat i 3 (nth i org)) ;平移变换
  173.     (setq j 0)
  174.     (repeat 3
  175.       (if RevFlag
  176.         (vlax-safearray-put-element mat i j (nth j (nth i lst)))
  177.                                         ;角度逆变换
  178.         (vlax-safearray-put-element mat i j (nth i (nth j lst)))
  179.                                         ;角度的变换
  180.       )
  181.       (setq j (1+ j))
  182.     )
  183.     (setq i (1+ i))
  184.   )
  185.   (vlax-safearray-put-element mat 3 3 1)
  186.   mat                                        ;返回矩阵
  187. )
  188.   (defun G:CrossProductor        (vec1 vec2 / a b c d e f)
  189.   ;;;   ;两矢量的叉积
  190.   (setq a (car vec1))
  191.   (setq b (cadr vec1))
  192.   (setq c (caddr vec1))
  193.   (setq d (car vec2))
  194.   (setq e (cadr vec2))
  195.   (setq f (caddr vec2))
  196.   (list
  197.     (- (* b f) (* c e))
  198.     (- (* c d) (* a f))
  199.     (- (* a e) (* b d))
  200.   )
  201. )
  202.   (if (and
  203.         xzj
  204.         (or (and (= (TYPE XZJ) 'VLA-OBJECT) (SETQ XZJ (LST->SS (LIST (vlax-vla-object->ename XZJ)))))
  205.             (and (= (TYPE XZJ) 'ENAME) (SETQ XZJ (LST->SS (LIST XZJ))))
  206.                                         ;如果传递进来的是一个图元,就自动转换一下
  207.             (and (= (TYPE XZJ) 'list)
  208.                  (= (TYPE (car XZJ)) 'ENAME)
  209.                  (SETQ XZJ (LST->SS xzj))
  210.             )                                ;如果传递进来是一个图元列表ss,就自动转换选择集
  211.             t
  212.         )
  213.         (= (type xzj) 'pickset)
  214.         (or (and qjblm (= (type qjblm) 'str) (> (strlen qjblm) 1))
  215.             (not qjblm)
  216.         )
  217.       )
  218.     (progn
  219.       (setq UcsFlag (getvar "WORLDUCS"))
  220.       (if (= UcsFlag 0)                        ;UCS是否与WCS相同
  221.         (setq UcsFlag T                        ;设置标志位为true
  222.               xdir    (getvar "UCSXDIR") ;X方向矢量
  223.               ydir    (getvar "UCSYDIR") ;Y方向矢量
  224.               zdir    (G:CrossProductor xdir ydir)
  225.                                         ;X和Y的方向矢量的叉积
  226.               origin  (getvar "UCSORG")        ;原点
  227.               WcsOrg  (trans '(0 0 0) 0 1) ;WCS的原点相对UCS的坐标
  228.               matLst  (list xdir ydir zdir) ;旋转的变换矩阵表
  229.               matrix  ($GetMatrix$ matLst origin nil)
  230.                                         ;从WCS到UCS的变换矩阵
  231.               revMat  ($GetMatrix$ matLst WcsOrg T) ;从UCS到WCS的变换矩阵
  232.         )
  233.         (setq UcsFlag nil)                ;否则不予变换
  234.       )
  235.       ;;在UCS下先变换物体到WCS下,取得每个物体的包围框,
  236.       ;;求出包围框集合的最小XY,最大XY,并用矩形框画出来
  237.       ;;然后把物体变换回到UCS,并把矩形也变换回去
  238.       (if (setq sel xzj)
  239.         ;;选择物体
  240.         (progn
  241.           (setq i 0)
  242.           (setq minPt (vlax-make-safearray vlax-vbdouble '(0 . 2)))
  243.                                         ;左下角点
  244.           (setq maxPt (vlax-make-safearray vlax-vbdouble '(0 . 2)))
  245.                                         ;右上角点
  246.           (repeat (sslength sel)
  247.             (if        (and (setq dxf nil
  248.                            dxf (entget (setq ent (ssname sel i)))
  249.                      )                        ;图元
  250.                      (or (AND (WCMATCH (CDR (ASSOC 0 DXF)) "*TEXT")
  251.                               (WCMATCH (CDR (ASSOC 1 DXF)) "[, ,,]")
  252.                                         ;空格或者是空值“”
  253.                          )                ;如果一个空格文字的话                        
  254.                          (and (= (cdr (assoc 0 dxf)) "HATCH")
  255.                               (= (cdr (assoc 93 dxf)) 1)
  256.                          )                ;反正93等于1的时候不能创建填充,但是遇到诡异的填充,93等于1就可以创建,既然93在诡异的情况下可以创建,那就用93=1来排除它,诡异的填充在这里:;(ENTMAKE (QUOTE ((0 . HATCH) (100 . AcDbEntity) (100 . AcDbHatch) (10 0.0 0.0 0.0) (210 0.0 0.0 1.0) (2 . SOLID) (70 . 1) (71 . 0) (91 . 1) (92 . 1) (93 . 1) (72 . 2) (10 3.67321e-006 -1.0 0.0) (40 . 1.0) (50 . 1.5708) (51 . 1.5708) (73 . 1) (97 . 0) (75 . 0) (76 . 1) (98 . 1) (10 97.2 305.1 0.0))))
  257.                      )
  258.                 )
  259.               ()                        ;以上条件成立以后,啥也不敢干呀
  260.               (PROGN
  261.                 (setq obj (vlax-ename->vla-object ent)) ;obj对象
  262.                 (and UcsFlag (vla-TransformBy obj revMat))
  263.                                         ;反变换到WCS
  264. ;;;                    (vla-GetBoundingBox obj 'minpt 'maxpt)
  265.                 (and (not (vl-catch-all-error-p
  266.                             (vl-catch-all-apply
  267.                               'vla-GetBoundingBox
  268.                               (list obj 'minPt 'maxPt)
  269.                             )
  270.                           )
  271.                      )                        ;得到包围框
  272.                      (setq minPt (vlax-safearray->list minPt))
  273.                      (setq maxPt (vlax-safearray->list maxPt))
  274.                      (setq minLs (cons minPt minLs)) ;得到左下角点表
  275.                      (setq maxLs (cons maxPt maxLs)) ;得到右上角点表
  276.                 )
  277.                 (and UcsFlag (vla-TransformBy obj matrix))
  278.                                         ;变换回到UCS
  279.               )
  280.             )
  281.             (setq i (1+ i))
  282.           )
  283.           (and minLs
  284.                (setq minX (apply 'min (mapcar 'car minLs)))
  285.                                         ;最小点集的最小X
  286.                (setq minY (apply 'min (mapcar 'cadr minLs)))
  287.                                         ;最小点集的最小Y
  288.           )
  289.           (and maxLs
  290.                (setq maxX (apply 'max (mapcar 'car maxLs)))
  291.                                         ;最大点集的最小X
  292.                (setq maxY (apply 'max (mapcar 'cadr maxLs)))
  293.                                         ;最打点集的最小Y
  294.           )
  295.           (and QJBLM
  296.                (Make-Rectange-getbox
  297.                  (list minX minY 0)
  298.                  (list maxX maxY 0)
  299.                  QJBLM
  300.                )
  301.           )                                ;构造边框
  302. ;;;          (and                                
  303. ;;;            UcsFlag                        ;如果UCS的话
  304. ;;;            (vla-TransformBy
  305. ;;;              (vlax-ename->vla-object (entlast))
  306. ;;;              matrix                        ;变换边框到UCS
  307. ;;;            )
  308. ;;;          )
  309.         )
  310.       )
  311.     )
  312.   )
  313.   (IF (AND minX minY maxX maxY)
  314.     (list (list minX minY 0) (list maxX maxY 0))
  315.   )
  316. )
  317. (defun c:ocr123 (/ 1/2p 1/2p-n bl box box-new ent ents html jbs l obj result s sbjg ss str strs)
  318.   (setq sbjg ($ocr-dwg$ (ssget)))
  319.   (SETQ BOX(CDR(ASSOC "坐标" sbjg)))
  320.   (setq strs (cdr (assoc "字串" sbjg)))
  321.   (if strs
  322.     (progn
  323.        (setq jbs(cdr(assoc "图元句柄" sbjg)))
  324.   (setq ents(mapcar 'handent jbs))
  325.   (setq ss (ssadd))
  326.   (mapcar(function(lambda (x) (ssadd x ss)))ents)
  327.   (if ss(vl-cmdf "change" ss "" "P" "C" 1 ""))
  328.   (setq ss nil)
  329.   (setq s nil)
  330.   (while (setq str (car strs))
  331.     (if  s
  332.       (setq s (strcat s "\n" str))
  333.       (setq s str)
  334.     )
  335.     (setq strs (cdr strs))
  336.   )
  337.   (setq str s)
  338.   (SETQ L(ABS(APPLY '-(MAPCAR 'CAR BOX))))
  339.   (SETQ L(* L 0.8))
  340.   (setq OBJ (vla-addmtext(vla-get-modelSpace(vla-get-ActiveDocument (vlax-get-acad-object)))(vlax-3d-point (list 0 0 0))(vlax-make-variant L 5)str))  
  341.   (SETQ ENT(VLAX-VLA-OBJECT->ENAME OBJ))
  342.   (SETQ BOX-NEW(GETBOX ENT NIL))
  343.   (SETQ BL(/(ABS(distance(car BOX)(cadr box)))(ABS(distance(car BOX-NEW)(cadr BOX-NEW)))))
  344.   (setq 1/2p(mapcar(function(lambda(x y)(* (+ x y)0.5)))(car BOX)(cadr BOX)))
  345.   (setq 1/2p-n(mapcar(function(lambda(x y)(* (+ x y)0.5)))(car BOX-NEW)(cadr BOX-NEW)))
  346.   (vla-ScaleEntity OBJ(vlax-3D-point 1/2p-n)bl)
  347.   (vla-move obj (vlax-3d-point 1/2p-n) (vlax-3d-point 1/2p))
  348.        (setq  html   (vlax-create-object "htmlfile")
  349.   result (vlax-invoke
  350.      (vlax-get (vlax-get html 'ParentWindow)
  351.          'ClipBoardData
  352.      )
  353.      'setData
  354.      "Text"
  355.      str
  356.          )
  357.   )
  358.   (vlax-release-object html)
  359.     )
  360.   )

  361. obj
  362. )


评分

参与人数 1明经币 +1 收起 理由
自贡黄明儒 + 1

查看全部评分

发表于 2023-6-10 08:59:22 | 显示全部楼层
很牛逼,win7用户路过
发表于 2023-6-10 09:00:46 | 显示全部楼层
错误: no function definition: GETBOX
发表于 2023-6-10 09:04:59 | 显示全部楼层
缺GETBOX函数,版主能不能把这个函数发出来
 楼主| 发表于 2023-6-10 09:05:06 | 显示全部楼层
TLQ 发表于 2023-6-10 09:00
错误: no function definition: GETBOX

已经补充了
 楼主| 发表于 2023-6-10 09:06:46 | 显示全部楼层
TLQ 发表于 2023-6-10 09:04
缺GETBOX函数,版主能不能把这个函数发出来

已经补充了
发表于 2023-6-10 10:14:59 | 显示全部楼层
我win10上找不到OCR.EXE
发表于 2023-6-10 10:39:26 | 显示全部楼层
非常支持楼主
发表于 2023-6-10 13:03:13 | 显示全部楼层
感谢大佬整理分享
您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|CAD论坛|CAD教程|CAD下载|联系我们|关于明经|明经通道 ( 粤ICP备05003914号 )  
©2000-2023 明经通道 版权所有 本站代码,在未取得本站及作者授权的情况下,不得用于商业用途

GMT+8, 2025-2-21 03:13 , Processed in 0.267892 second(s), 30 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表