51Testing软件测试论坛
标题:
求教一个可靠性高,且性能好的图片验证方法
[打印本页]
作者:
yaowei
时间:
2010-2-3 18:16
标题:
求教一个可靠性高,且性能好的图片验证方法
求教一个可靠性高,且性能好的图片验证方法。以下是我写的图片匹配方法,可靠性稍好,但是性能比较低。不符合使用要求,请高手指点一下,哪里可以优化或者有其它好的算法。这个方法在32位显示模式下匹配比16位显示模式下可靠性高,我希望是在不同模式下都有高可靠性和性能。谢谢了。
import java.awt.AWTException;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.PixelGrabber;
import java.io.File;
import java.io.IOException;
import java.util.Calendar;
import javax.imageio.ImageIO;
import resources.IdentifyByAberrationHelper;
import com.rational.test.ft.*;
import com.rational.test.ft.object.interfaces.*;
import com.rational.test.ft.object.interfaces.SAP.*;
import com.rational.test.ft.object.interfaces.WPF.*;
import com.rational.test.ft.object.interfaces.dojo.*;
import com.rational.test.ft.object.interfaces.siebel.*;
import com.rational.test.ft.object.interfaces.flex.*;
import com.rational.test.ft.script.*;
import com.rational.test.ft.value.*;
import com.rational.test.ft.vp.*;
/**
* Description : Functional Test Script 色差法图片识别
* @author
*/
public class IdentifyByAberration extends IdentifyByAberrationHelper
{
public static int _MODELER_CHRABE = 40; //像素误差值,该值可根据情况适当调整
public static double xyz [][] = new double[2][3]; //XYZ
public static int rgb [][] = new int[2][4]; //RGB
public static double lab [][] = new double[2][3]; //LAB
public static ColorModel cm = ColorModel.getRGBdefault();
public static double delta [] = new double[4]; //delta
/**
* Script Name : <b>IdentifyByAberration</b>
* Generated : <b>2010-2-3 上午10:57:56</b>
* Description : Functional Test Script
* Original Host : WinNT Version 5.1 Build 2600 (S)
*
* @since 2010/02/03
* @author
*/
public void testMain(Object[] args)
{
RootTestObject root = RootTestObject.getRootTestObject();
//BufferedImage imgSrc = root.getScreenSnapshot(new Rectangle(21,376,31,33));
BufferedImage imgSrc = root.getScreenSnapshot(new Rectangle(0,0,250,550));
String imgBase = "F:\\desktop.png";
try {
System.out.println(Calendar.getInstance().getTime());
Point point = findFistImg(imgSrc,ImageIO.read(new File(imgBase)));
System.out.println(Calendar.getInstance().getTime());
if(point != null)
{
System.out.println(point);
Robot robot;
try {
robot = new Robot();
//robot.mouseMove(point.x+21, point.y+376);
robot.mouseMove(point.x, point.y);
//sleep(20);
} catch (AWTException e) {
e.printStackTrace();
}
}else{
System.out.println("null");
}
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 在目标图片中查找指定图片
* @param formImg 目标图片
* @param ctrlImg 指定图片
* @return Point-图片中心坐标 null-未找到
* @throws IOException
*/
public static Point findFistImg(BufferedImage formImg, BufferedImage ctrlImg) throws IOException
{
int formWidth = formImg.getWidth();
int formHeight = formImg.getHeight();
int ctrlWidth = ctrlImg.getWidth();
int ctrlHeight = ctrlImg.getHeight();
Point start = new Point(0, 0);
Point center = new Point(0, 0);
boolean findIt = false;
int[] CtrlPixels = new int[ctrlWidth * ctrlHeight];
int[] FormPixels = new int[formWidth * formHeight];
try
{
PixelGrabber pg1 = new PixelGrabber(ctrlImg, 0, 0, ctrlWidth,ctrlHeight, CtrlPixels, 0, ctrlWidth);
pg1.grabPixels();
PixelGrabber pg2 = new PixelGrabber(formImg, 0, 0, formWidth,formHeight, FormPixels, 0, formWidth);
pg2.grabPixels();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
for (int y = 0; y < formHeight - ctrlHeight; ++y)
{
for (int x = 0; x < formWidth - ctrlWidth; ++x)
{
start.x = x;
start.y = y;
findIt = isItHere(start, FormPixels, formWidth,CtrlPixels, ctrlWidth, ctrlHeight);
if (findIt)
{
break;
}
}
if (findIt)
{
break;
}
}
if (findIt)
{
center.x = start.x + ctrlWidth / 2;
center.y = start.y + ctrlHeight / 2;
return center;
}
return null;
}
/**
* 比较目标图片当前坐标对应的局部图片是否与基准图片一样
* @param start 当前坐标
* @param FormPixels 目标图片像素集合
* @param formWidth 目标图片宽度
* @param CtrlPixels 基准图片像素集合
* @param ctrlWidth 基准图片宽度
* @param ctrlHeight 基准图片高度
* @return true-一样 false-不一样
*/
private static boolean isItHere(Point start, int[] FormPixels,int formWidth, int[] CtrlPixels, int ctrlWidth,int ctrlHeight)
{
boolean b = true;
for (int y = 0; y < ctrlHeight; ++y)
{
for (int x = 0; x < ctrlWidth; ++x)
{
b = compareByColorDiff(CtrlPixels[y * ctrlWidth + x],FormPixels[(start.y + y) * formWidth + start.x + x]);
if(b == false)
{
return false;
}
}
}
return b;
}
/**
* 在目标对象中查找指定图片
* @param form 目标对象
* @param controlImgFile 指定图片路径
* @return Point-图片中心坐标 null-未找到
* @throws IOException
*/
public static Point findFistImg(TopLevelSubitemTestObject form,String controlImgFile) throws IOException
{
form.click(new Point(5, 5));
BufferedImage formImg = form.getImage("");
BufferedImage ctrlImg = ImageIO.read(new File(controlImgFile));
return findFistImg(formImg, ctrlImg);
}
/**
* 色差法比较两个像素点是否一样
* @param basePixel 基准像素点
* @param sorcPixel 目标像素点
* @return true-一样 false-不一样
*/
public static boolean compareByColorDiff(int basePixel,int sorcPixel)
{
setRGB(basePixel,sorcPixel);
setXYZ();
setLAB();
setDeltaE();
if (delta[3] > _MODELER_CHRABE)
{
return false;
}else{
return true;
}
}
/**
* 获得基准像素点和目标像素点的RGB值
* @param basePixel 基准像素点
* @param sorcPixel 目标像素点
*/
public static void setRGB(int basePixel,int sorcPixel)
{
rgb[0][0] = cm.getRGB(basePixel);//基准像素点RGB值
rgb[0][1] = cm.getRed(basePixel);//基准像素点R值
rgb[0][2] = cm.getGreen(basePixel);//基准像素点G值
rgb[0][3] = cm.getBlue(basePixel);//基准像素点B值
rgb[1][0] = cm.getRGB(sorcPixel);//目标像素点RGB值
rgb[1][1] = cm.getRed(sorcPixel);//目标像素点R值
rgb[1][2] = cm.getGreen(sorcPixel);//目标像素点G值
rgb[1][3] = cm.getBlue(sorcPixel);//目标像素点B值
}
/**
* 获得基准像素点和目标像素点的XYZ值
*/
public static void setXYZ()
{
xyz[0][0] = (0.490*rgb[0][1] + 0.310*rgb[0][2] + 0.200*rgb[0][3]) / (0.667*rgb[0][1] + 1.132*rgb[0][2] + 1.200*rgb[0][3]);//基准像素点X值
xyz[0][1] = (0.117*rgb[0][1] + 0.812*rgb[0][2] + 0.010*rgb[0][3]) / (0.667*rgb[0][1] + 1.132*rgb[0][2] + 1.200*rgb[0][3]);//基准像素点Y值
xyz[0][2] = (0.000*rgb[0][1] + 0.010*rgb[0][2] + 0.990*rgb[0][3]) / (0.667*rgb[0][1] + 1.132*rgb[0][2] + 1.200*rgb[0][3]);//基准像素点Z值
xyz[1][0] = (0.490*rgb[1][1] + 0.310*rgb[1][2] + 0.200*rgb[1][3]) / (0.667*rgb[1][1] + 1.132*rgb[1][2] + 1.200*rgb[1][3]);//目标像素点X值
xyz[1][1] = (0.117*rgb[1][1] + 0.812*rgb[1][2] + 0.010*rgb[1][3]) / (0.667*rgb[1][1] + 1.132*rgb[1][2] + 1.200*rgb[1][3]);//目标像素点Y值
xyz[1][2] = (0.000*rgb[1][1] + 0.010*rgb[1][2] + 0.990*rgb[1][3]) / (0.667*rgb[1][1] + 1.132*rgb[1][2] + 1.200*rgb[1][3]);//目标像素点Z值
if (rgb[0][0] == -16777216) //基准像素点RGB值
{
xyz[0][0] = 0;
xyz[0][1] = 0;
xyz[0][2] = 0;
}
if (rgb[1][0] == -16777216) //目标像素点RGB值
{
xyz[1][0] = 0;
xyz[1][1] = 0;
xyz[1][2] = 0;
}
}
/**
* 获得基准像素点和目标像素点的LAB值
*/
public static void setLAB()
{
double x,y,z;
x = xyz[0][0] / 95.047;
y = xyz[0][1] / 100.000;
z = xyz[0][2] / 108.883;
if(x>0.008856)
{
x = Math.pow(x, 1.0/3.0);
}else
{
x = (7.787*x) + (16/116);
}
if(y>0.008856)
{
y = Math.pow(y, 1.0/3.0);
}else
{
y = (7.787*y) + (16/116);
}
if(z>0.008856)
{
z = Math.pow(z, 1.0/3.0);
}else
{
z = (7.787*z) + (16/116);
}
lab[0][0] = 116*Math.pow(y, 1.0/3.0) - 16;//基准像素点L值
lab[0][1] = 500*(Math.pow(x, 1.0/3.0) - Math.pow(y, 1.0/3.0));//基准像素点A值
lab[0][2] = 200*(Math.pow(y, 1.0/3.0) - Math.pow(z, 1.0/3.0));//基准像素点B值
x = xyz[1][0] / 95.047;
y = xyz[1][1] / 100.000;
z = xyz[1][2] / 108.883;
if(x>0.008856)
{
x = Math.pow(x, 1.0/3.0);
}else
{
x = (7.787*x) + (16/116);
}
if(y>0.008856)
{
y = Math.pow(y, 1.0/3.0);
}else
{
y = (7.787*y) + (16/116);
}
if(z>0.008856)
{
z = Math.pow(z, 1.0/3.0);
}else
{
z = (7.787*z) + (16/116);
}
lab[1][0] = 116*Math.pow(y, 1.0/3.0) - 16;//目标像素点L值
lab[1][1] = 500*(Math.pow(x, 1.0/3.0) - Math.pow(y, 1.0/3.0));//目标像素点A值
lab[1][2] = 200*(Math.pow(y, 1.0/3.0) - Math.pow(z, 1.0/3.0));//目标像素点B值
}
/**
* 获得基准像素点和目标像素点的差值
*/
public static void setDeltaE()
{
delta[0] = lab[0][0] - lab[1][0];//deltaL
delta[1] = lab[0][1] - lab[1][1];//deltaA
delta[2] = lab[0][2] - lab[1][2];//deltaB
delta[3] = Math.pow((Math.pow(delta[0], 2) + Math.pow(delta[1], 2) + Math.pow(delta[2], 2)), 0.5);//deltaE
}
}
作者:
dreamever
时间:
2010-2-5 11:43
如果图片比较采用逐点比较的话,效率提升的空间不大,试想,对于一个1440 *900的显示器,它要比较的象素点不会少于1296000,而且通过LAB的方式还要经过比较复杂的换算。
一个变通的方法是可以隔点取样,例如每隔两个或者三个象素比较一次,这样可以减少比较次数,并且肉眼上不会有太大的差异,可是间隔太大不能太大,我这边如果间隔的象素超过8个,就会有测试上的误差。
另外,楼主的代码里对双精度的类型没有做任何转换,我觉得这可能需要考虑一下,我一般都是用Double.valueof(),或者BigDecimal对象来转换一下,不然运算和比较结果时会有问题
作者:
dennyqiang
时间:
2010-2-22 23:37
RFT自带有图片验证点,不知道能不能将其提取出来使用。我估计是可以考虑的,而且网络上应该有相应的JAR包下载吧,没有自己写过,所以没怎么去,所以没有去研究。
欢迎光临 51Testing软件测试论坛 (http://bbs.51testing.com/)
Powered by Discuz! X3.2