跳至主要内容

用DOS批处理来做数字图像处理

用DOS批处理来做数字图像处理

redraiment, 2009-07-03

前言





  我最近对语言挺着迷的,很想学习一下《编译原理》。询问了老师才知道我们已经取消了这么课程(他们觉得学了没用) ,一时间也没找到什么好的教材,如果有好心的朋友可以推荐几本关于编译原理的经典书籍,感激不尽!

正文

  图灵机是由输入、输出和状态转移函数三要素组成的,广义上的自动机模型。理论上讲任何任何完备图灵机语言都可用于通用编程,并且和其他完备图灵机语言一样有效。但实际上有些此类语言作用在其特定领域之外时可能令人非常痛苦。例如m4是一种有意的完备图灵机,但实践中把m4当作通用语言使用则非常困难。


  最近对一些计算机语言进行分析,总结一门最简单的可编程的语言也应该具备:

  • 输入输出。获得待处理的数据,可以是从标准输入输出,也可以从文件;
  • 算数运算。计算机的核心当然是“计算”,就是普通计算机上提供的加减乘除运算;
  • 内存管理:临时变量值的获取和存储管理,其实有点像通过变量名来查找值的Hash表(这在DOS的批处理中体现的很到位);
  • 按条件跳转:拥有条件判断(test),加上语句跳转(jump),就能模拟出if、while、for和goto等语句(其中goto的条件为永真,就执行“test(true) jump xxx”一样)。


  按照上面的说法,程序解释器很像是一个功能加强了的计算器(原来写个计算器也这么不容易,以前低估它了T_T)。纵观周围的工 具,很多看似简陋的小工具原来都符合上面的要求。像UNIX里的命令行计算器bc(1)/dc(1),都是完备图灵机;DOS的批处理同样也具备,下面来详细讨论。


  批处理中可以用set 给变量赋值; set /a 可以进行算数运算,在命令行中执行set /? 可以查看所有支持的运算符;另外还有if、for、call、goto等语句支持跳转; set /p 和echo 可以实现从键盘和屏幕上输出文本信息,但对二进制文件的操作显得有点力不从心(可以用debug 来实现,但貌似 挺复杂)。所以我用C语言写了两个小程序(Bmp2Txt和Txt2Bmp,可到子清行下载二进制文件和C语言源码),解决批处理对BMP文件的输入输出。下面是我用这两个小工具写的拉普拉斯算子求边缘检测的批处理源码:

::用拉普拉斯算子来做边缘检测
@echo off
setlocal enabledelayedexpansion
if not "%~x1"==".bmp" goto error
if not "%~x2"==".bmp" goto error

Bmp2Txt %1 $$temp$$.txt
::将BMP的像素集合保存到数b
call Txt2Array b < $$temp$$.txt
set t.width=!b.width!
set t.height=!b.height!
for /l %%y in (0,1,!b.height!) do (
    for /l %%x in (0,1,!b.width!) do (
        set ny=%%y
        set nx=%%x
        call :calc
    )
)

::将数组转换成文本文件
call Array2Txt t > $$temp$$.txt
Txt2Bmp %2 $$temp$$.txt
del /q $$temp$$.txt
goto end

::Functions
:error
echo.&echo  usage: %0 Input_BMP_File Output_BMP_File
goto end

:calc
set /a t[%ny%][%nx%]=4*!b[%ny%][%nx%]!
set /a dy=%ny%-1
set /a dx=%nx%
if defined b[%dy%][%dx%] set /a t[%ny%][%nx%]-=!b[%dy%][%dx%]!

set /a dy=%ny%+1
set /a dx=%nx%
if defined b[%dy%][%dx%] (set /a t[%ny%][%nx%]-=!b[%dy%][%dx%]!)

set /a dy=%ny%
set /a dx=%nx%-1
if defined b[%dy%][%dx%] (set /a t[%ny%][%nx%]-=!b[%dy%][%dx%]!)

set /a dy=%ny%
set /a dx=%nx%+1
if defined b[%dy%][%dx%] (set /a t[%ny%][%nx%]-=!b[%dy%][%dx%]!)

goto :eof

:end


  在我的机子上跑了一两分钟居然也跑出结果来了,相应的效果图如下。


  原始图:原始图


  处理后的图片:Laplace处理后的图片




评论

此博客中的热门博文

AutoHotKey 新手入门教程

AutoHotKey 真是一个好玩的工具!短短几行代码就是先了“窗口置顶”、“窗口透明”等功能,之前我还特意为此装了好几个小工具,现在都可以卸掉了。闲来无事,就把 Quick Start 翻译了一下,我没有逐字逐句地翻译,有时候我嫌原文罗嗦就用自己的话概括地描述了一下。 原文地址:http://www.autohotkey.com/docs/Tutorial.htm 教程目录 创建脚本 启动程序 模拟鼠标键盘 操纵窗口 输入 变量与剪切板 循环 操纵文件 其他特性 创建脚本 每个脚本都是一个纯文本文件,由一些能被 AutoHotKey.exe 执行的命令组成。一个脚本可能还包含 热键 和 热字符串 。如果没有热键和热字符串,脚本在启动的时候就会从头依次执行到尾。 创建一个新的脚本: 下载 并安装 AutoHotkey。 右击鼠标,选择 新建 -> 文本文档 。 输入文件名并确保以 .ahk 结尾。例如:Test.ahk。 右击文件,选择 编辑脚本 。 输入以下内容:#space::Run www.google.com 上一行的第一个字符 "#" 代表键盘上的 Windows 键;所以 #space 表示在按住 Windows 键后再按空格键。"::" 后面的命令会在热键激活后执行,在本例中则会打开谷歌主页。继续按下面步骤操作,来执行这个脚本: 保存并关闭该文件。 双击该文件来启动它。在系统托盘里会出现一个新图标。 按下 Windows 和空格键,网页会在默认的浏览器里打开。 右击系统托盘里的绿色图标可以退出或编辑当前脚本。 注意: 可以同时启动多个脚本,并且在系统托盘里都会有一个相应的图标。 每个脚本都能定义多个 热键 和 热字符串 。 想让某个脚本开机即启动,可以将它的 快捷方式放到开始菜单的启动目录里 。 启动程序 命令 Run 可以运行程序、打开文档、网页链接或快捷键。请参看以下示例: Run Notepad Run C:\My Documents\Address List.doc Run C:\My Documents\My Shortcut.lnk Run www.yahoo.com Run mailto:someone@somedoma

sed单行脚本学习笔记

Sed单行脚本学习笔记 redraiment, 2009-12-31 回家真好   前段时间忙着找工作、项目结题、写报告……反正是总有做不完的事情,哈哈。好在暂时告一段落了,应老妈强烈要求回家休息几天。这次回家除了这身衣服,只带了一本《 sed与awk 》,我觉得这种小册子最适合茶余饭后休闲之用。如果你也有兴趣学 sed ,推荐你一起看《 sed与awk 》(可以在 谷歌图书 在线阅读英文版:D)。   花了两天时间,看完了前面 sed 的部分。要掌握一个工具就要熟悉它的规则,man 等参考手册向我们介绍这些规则,教程则演示如何使用这些规则,但要将这些规则运用自如,还需要去理解别人的代码并尝试自己解决问题。在 SourceForge 上有份经典的文档:《 SED单行脚本快速参考 》(单行脚本要求命令行长度小于65个字符),由 Eric Pement 整理, Joe Hong 翻译,通篇阅读后获益良多,故撰此文和大家分享。 精彩脚本摘录 # 在每一行后面增加一空行 sed G   在参考手册中,命令G的作用是“将换行符后的保持空间内容追加到模式空间”。就像前文提到的,看过教程后只是熟悉了规则,还不能将规则运用自如,我自己写的代码是:sed 's/$/\n/',就是因为我还不熟悉每个命令会对模式空间产生什么影响。所以看到这段参考代码时感觉眼前一亮:“原来还可以这样写!” # 显示文件中的最后10行 (模拟“tail”) sed -e :a -e '$q;N;11,$D;ba'   假设文件有 N 行(N 大于10),显示最后10行也就意味着删除前的 N-10 行。在多行模式中,命令“D”可以删除模式空间中第一行;命令“N”可以将下一行追加到模式空间中,建立多行模式。因此问题转化为:“1)将整个文件的内容放入一个模式空间中;2)删除前 N-10 行。”其中问题1)通过控制语句“b”来解决:sed ':a; N; ba';至于问题二,模式“1,$”代表文本中的所有行,因此紧跟着的命令被执行N次,同理,模式“11,$”匹配后面的 N-10 行,因此“11,$D”一个执行了 N-10 次。   其实,在 GNU sed 中,命令“$q”是可以删掉的,因为在最后一行执行命令“N”就会因出错而自动退出。   另外,在

DAO层测试

<dependency> <groupId>com.wix</groupId> <artifactId>wix-embedded-mysql</artifactId> <version>2.1.4</version> <scope>test</scope> </dependency> 利用 wix-embedded-mysql 把MySQL嵌入到进程中,作为内存型的MySQL来做单元测试。 脚本: resources/migrations/mysql/<database>/<timestamp>_<action>.sql 但多个项目需要共享数据库脚本,可能可以用 git submodule 共享。