image图像库

 

一、创建图片对象

颜色对象是一个userdata类型的变量,可以使用下面的函数来创建新的颜色对象。

img = image.new()
img = image();

创建空的图片对象。

因为image.new 是image库的默认函数,image()等效于image.new();

img = image.new(width,height,bpp)
img = image(width,height,bpp);
参数分别为图片宽,图片高,图片位数。最后一个参数可以省略(默认bpp值为24)。

img = image.new(filename)
img = image(filename)
从指定的路径载入新的图片对象。例:

img = image.new("c:\\test,jpg")

img2 = image.new(img)
img2 = image(img)
拷贝新的图片对象。

userdata、table、function这三种数据类型在赋值时仅添加一个新的引用而不是拷贝新的对象。
img2 = img这样两个变量是指向同一个图片对象,而 img2 = image.new(img) 是拷贝一个新的图片对象。

二、释放图片对象

image.del(img)
立即删除img对象。并不会删除img这个变量(img指向无效的图片对象)。

img = nil;
立即删除img变量,等待垃圾收集器删除img引用的图片对象

三、存取图片文件

image.load(img,filename)
img:load(filename)
读取图片文件,filename参数指定图片路径。
成功返回true,失败返回false。

--创建图片对象
img = image.new();

--用assert函数检查img:load的返回值是否为true,
--将win.lastError的第二个返回值作为错误信息.

assert( img:load("nofile.jpg"),select( 2, win.lastError()) );


image.save(img,filename)
img:save(filename)
保存图片文件,filename参数指定图片路径。
成功返回true,失败返回false。

注意图片的bpp值必须符合图片格式,例如小于24位的图像不应保存为jpg图片而应保存为bmp图片。

四、存取剪贴板图片

image.setClipBD(img)
img:setClipBD()
把图片发送到剪贴板

image.getClipBD(img)
img:getClipBD()
从剪贴板读取图像

五、下载图像

image.getURL(img,"网址","*.默认后缀名")
img:getURL("网址","*.默认后缀名")?
第一个参数指定网址,如果网址中包含正确的图片后缀名,那么第二个参数可以省略。

例:

img = image.new();
img:getURL("http://bbs.test.net/code.asp","*.bmp");

六、抓屏

image.capture(img,hwnd,x,y,cx,cy)
img:capture(hwnd,x,y,cx,cy)
快速抓屏,hwnd 指定窗口句柄,如果为0指定桌面窗口。
x,y指定左上角坐标,cx,cy指定宽、高 ,如果都为零都抓取整个窗口的图像。
省略全部抓屏参数,使用 img:capture() 则抓取全屏图像。

image.captureX(img,hwnd,x,y,cx,cy)
img:captureX(hwnd,x,y,cx,cy)

用法与image.capture相同,抓屏速度较慢。

也可以通过模拟按键启用外部抓屏,并且从剪贴板获取图像,下面是一个例子。
--按下抓屏热键
key.press("PRINT_SCREEN");
--适当的延时等待抓屏成功
delay(100);

--创建新的图片对象
img = image.new();
--从剪贴板获取图片
img:getClipBD();


七、读取、设置图片属性

ok = image.ok(img)
ok = img:ok()
检测图片是否有效,有效返回true,无效返回false。

x,y = image.size(img)
x,y = img:size()
返回图片大小。

x,y = image.size(img,cx,cy)
img:size(cx,cy)
重新设置图片大小(放大或缩小)。

image.Crop(img, x,y,x2,y2 )
img:Crop( x,y,x2,y2 )
参数指定一个矩形的左(x),上(y),右(x2),下(y2)坐标,并沿矩形区域修剪图片。

num = image.bpp(img,0)
num = img:bpp(0)
返回图片位深度

image.bpp(img,num)
img:bpp(num)
设置图片位深度。 可指定以下值 1(黑白) 4(16色) 8(256色) 24(真彩色)。

image.median(img,r)
img:median(r)
中值滤波(去杂点),参数r指定半径。
这个函数在识别验证码的时候有用,较小的图片会被严重破坏,但是可以有效的得到特征点。
例: img:median(3);

image.repair(img,r,n )
img:repair( r, n)
修复被破坏的图片,第一个参数r为修复半径,第二个参数n指定修复的次数。
例:img:repair( 0.25, 2);

八、分割图像

1、显示指定行列平均分割

例:

img2,img3,img4,img5 = img:split(1,4) --平均分割成一行四列,返回四个图片对象


2、仅指定一个参数并且参数为字符串值,按颜色通道分离(图片大小不变,可用于去杂色、杂点)

img2,img3,img4 = img:split("RGB")
img2,img3,img4,img5 = img:split("CMYK")
img2,img3,img4 = img:split("HSL")
img2,img3,img4 = img:split("XYZ")
img2,img3,img4 = img:split("YIQ")
img2,img3,img4 = img:split("YUV")


3、仅指定一个参数并且参数为数字值,自动分割(仅适用于单色图片),
例如:img:split(8) 其中8指定杂点系数,杂点越多,杂点系数就应当设置的较大。
必须反复测试找到正确的杂点系数,否则分割的效果不好。

九、合并图片

image.mix(img,img2,mode,x,y)
img:mix(img2,mode,x,y)
混合两张图片,mode参数指定混合模式,参数x,y指定偏移坐标。

下面是一个完整的例子:

_MIX_COPY = 0;
--将源图片直接拷贝到目标图片上
_MIX_MASK = 1;
--源图片黑色(颜色值0)部份擦除目标图片颜色
_MIX_DSTMASK = 2;
--目标图片透明背景部份显示源图片(即将目标图片覆盖在源图片上面,背景透明)
_MIX_SRCMASK = 3;
--源图片与目标透明色相同部份显示目标图片(即将源图片覆盖在目标图片上面,背景透明)
_MIX_SRCMASK2 = 4;
--同上,使用源图片透明色
_MIX_DSTBLEND = 5;
_MIX_SCREEN = 6;
_MIX_ADD = 7;
_MIX_SUB = 8;
_MIX_AND = 9;
_MIX_XOR = 10;
_MIX_OR = 11;
 
import("std"); --也可以使用这句导入标准库的定义,就不需要声明上面的变量了
 
w,h = win.getScreen(); --得到屏幕大小
 
--创建两个图片
img_left = image.new();
img_right = image.new();
 
img_left:capture(0,0,0,w/2,h); --抓屏屏幕的左半部份(宽度除2 w/2 )
img_right:capture(0,w/2,0,w/2,h); --抓屏屏幕的右半部份(起始x坐标为 w/2 宽度为 w/2)
 
img_left:save("c:\\左半部份.jpg")
img_right:save("c:\\右部部份.jpg")
 
img = image.new( w,h ,24); --创建一个全屏大小的图片
img:mix(img_left,_MIX_COPY,0,0); --把左半部份贴到img的左面
img:mix(img_right,_MIX_COPY,w/2,0); --把右半部份贴到img的右面(起始x坐标为 宽度除2 w/2)
img:save("c:\\合成的全屏.jpg"); --如予期的,左右合成了一个完整的图片 

十、读写指定坐标的颜色

num = image.getPos(img,x,y)
num = img:getPos( x,y)
x,y指定图片坐标,返回图片指定坐标的颜色数字值.

image.setPos(img, x, y, num )
img:setPos(x,y, num)
x,y指定图片坐标,设置图片指定坐标的颜色数字值.

左侧边距为x,上侧边距为y,当 x=0,y=0时,指向的点为图片的第一个像素。

下面是一个完整的例子:
img = image.new(300,200,24); --创建宽300,高200,bpp=24的图像
 
s_nLisXCoef = 1;
s_nLisYCoef = 3;
s_nLisYOffset = 44;
cl = color( 255 , 80 ,255 ); --画线的颜色
nCL = cl + 0;
 
m_pixelsX,m_pixelsY = 300,200; --读取图像宽度
 
s_nLisXCoef = s_nLisXCoef + 1;
s_nLisYCoef = s_nLisYCoef + 1;
 
x=0;y=0;
for t=0,32767,0.2 do
    x = math.sin( s_nLisXCoef * t) * m_pixelsX/2 + m_pixelsX/2;
    y = math.sin( s_nLisYCoef*t + s_nLisYOffset)*m_pixelsY/2 +m_pixelsY/2;
    img:setPos(x ,y,nCL);
end;
 
 
img:paint(100,100,300 ,200 ) --输出到屏幕看看

img:save("d:\\test.jpg") --保存到文件看看

十一、在图像上查找指定颜色

image.findColor(img,cl,x,y,x2,y2)
img:findColor(cl,x,y,x2,y2)

在图像上搜索指定颜色的点。
其中cl指定颜色,可以是color对象,或者数字值,或者形如"#FFFFFF"的字符串表达式

下面是一个例子,实现同样的功能,就比color.find快了近十倍。

img=image.new();--创建图象
img:capture();--抓屏

img:bpp(8); --可以通过bpp函数求近似色

cl = color("#FFFFFF");
cl:bpp(8); --可以通过bpp函数求近似色

x,y =img:findColor(cl,0,0,1024,768);

--win.consoleOpen()
mouse.setPos(x,y,true); --移动鼠标到指定位置
print(x,y);


十二、读取、设置图片二进制数据。

str = image.getBits(img,row)
str = img:getBits(row)
参数row指定行号,row等于1为第一行。
读取图片指定行的二进制数据。

例:

img = image.new();--创建新的图片对象
img:capture();--抓屏

str = img:getBits(1); --读取图片第一行二进制数据。
r = string.byte(str ,3 ); --得到第三个字节
g = string.byte(str ,2 ); --得到第二个字节
b =string.byte(str ,1 ); --得到每一个字节

win.messageBox( tostring(color(r,g,b) == color( img:getPos(0,0)) ) )


image.setBits(img,row,str)
img:setBits(row,str)
参数row指定行号,row等于1为第一行。
设置图片指定行的二进制数据。

下面是一个例子:

img = image.new(300,200,24); --创建宽300,高200,bpp=24的图像
 
tab = {} --创建一行颜色数据列表,每个像素点三位(bpp=24)
for i=0,300,1    do   
   tab[i*3+1]math.mod(i+5,255); --B
   tab[i*3+2]math.mod(i+25,255); --G
   tab[i*3+3]math.mod(i+155,255); --R
end;
 
 
for i=1,200,1    do 
   str = string.char( unpack(tab) ); --将列表转换为string
   img:setBits(i,str); -- i为行号 str为图像数据
end;
 
img:paint(100,100,300 ,200 ) --输出到屏幕看看

img:save("d:\\test.jpg") --保存到文件看看

-- 实际上,这是一个矩阵数组,参考数据结构-->建立矩阵的方法二

str = image.getBytes(img,"*.后缀名")
str = img:getBytes("*.后缀名")
读取图片的二进制数据,参数指定后缀名。

image.setBytes(img,str ,"*.后缀名")
img:setBytes(str,"*.后缀名");
将二进制数据还原为图片对象。
最后一个参数指定后缀名,必须与调用image.getBytes时使用的后缀名相同。

在ApeML中存储图像或者序列化到XML文件、或者其他需要显示字符串的地方,必须将二进制数据base64编码为纯文本。例如:

img = image.new();--创建新的图片对象
img:capture();--抓屏

--读取二进制数据 并进行base64编码转换为普通文本

str = string.encode( img:getBytes("*.bmp") , ""); -- "*.bmp"指定图像格式
string.save(str ,"c:\\test.txt");--保存为纯文本文件。

--还原图像
img:setBytes( string.decode( str ,"") ,"*.bmp"); -- 必须与img:getBytes使用的后缀名相同

十三、比较图像

image.test(img,img2)
img:test(img2)
比较图像 0 < 返回差异值 < (img面积 + img2面积)
image.test返回图像差异值,完全相似返回0 完全不相似为两个图片的面积相加。
image.test比较速度最快,可以比较任意图片(不要求大小相同),但是精确匹配能力一般,模糊识别的能力较强。
不适合用于图文识别。

image.testX(img,img2)
img:testX(img2)
比较图像 0 < 返回差异值 < 1
image.testX返回差异值,完全一样为0,完全不一样为1,通常返回的是1到0之间的小数,数字越小表示两个图片越接近相似。
image.testX速度较慢,适合比较较大的图片(不要求大小相同),精确匹配能力较差,模糊识别的能力一般。
适用于图文识别。

image.testXX(img,img2)
img:testXX(img2)
比较图像 0 < 返回差异值 < img面积
image.testXX返回相似度,完全一样为0,完全相似返回0 完全不相似为单个图片的面积。
image.testXX速度一般,适合比较小图片(要求两张图片大小相同),精确匹配能力最强,模糊识别的能力最差。
适用于图文识别。

以上的三个函数都返回一个值,表示两个图像的差异度(就是两个图像不相同的比率,即"相似度"的反义词)
这三个函数,最小值都是相同的,都是 0 ,(差异度等于0,表示两个图片完全相似,即相似度为百分之百)
而他们的最大值是不同的,参考上面的说明。

十四、在屏幕上查找图像

image.find(img,img2,x,y,x2,y2,step)
x,y,sm = img:find(img2,x,y,x2,y2,step)

img是要查找的图像,img2参数是屏幕图像,在img2里面查找img。
参数x,y,x2,y2指定要查找的范围,x、y为左上角坐标,x2、y2为右下角坐标。
step参数指定步进。

返回值x,y 为找到的坐标,sm为相似度,为0到100之间的值,100为完全相似,0为完全不相似

img:find()函数与“模拟区块--抓图移动”的功能类似,参数也类似。 .

除了img2以外,其他的参数可以忽略:

x,y,sm = img:find(img2,0,0,0,0,5)
img:find(img2) --查找范围为img2的大小
img:find(img2,0,0)
img:find(img2,0,0,0,0)
img:find(img2,0,0,0,0,5)
--以上的写法都是正确的。

十五、在屏幕上显示图像

image.paint(img,x,y,cx,cy )
img:paint(x,y,cx,cy )

在屏幕上显示图像,参数分别为左坐标(x),上坐标(y),宽(cx),高(cy)。

十六、从句柄获取为图片对象

ok,x,y = image.fromHICO(img,hicon,mode)
ok,x,y = img:fromHICO(hicon,mode)
hicon指定图标句柄,第二个参数设置转换选项(这是可选参数,可以省略)
返回值ok表示转换是否成功,x,y为指针类图标热区偏移值。

mode参数可选项如下:

ok,x,y = img:fromHICO(hico); --返回图标
ok,x,y = img:fromHICO(hico,1); --返回外观图案
ok,x,y = img:fromHICO(hico,2); --返回掩码图

image.fromHBMP(img,hbmp,bpp)
img:fromHBMP(hbmp,bpp)
hbmp指定位图句柄,bpp参数指定颜色位数(这是可选参数,可以省略)