1. 前言

本来这次文章的title是写成和前几篇类似的《EasyMonkeyDevice API实践全记录》,内容也打算把每个API的实践和建议给记录下来,但后来想了下觉得这样子并不是最好的方法,鉴于EasyMonkeyDevice其实就是在前几章描述的MonkeyDevice和HierarchyViewer的基础上加了一层Wrapper,把原来的通过接受坐标点或者ViewNode来操作控件的思想统一成通过控件ID来操作,其实最终它们都会转换成坐标点或ViewNode进行操作。以touch和visible这两个API为例子,大家看下以下的源码就很清楚了。

MonkeyDevice里面的touch是用坐标点作为参数的,而下面的EasyMonkeyDevice用得是id(By这个类里面就一个ID而已,有兴趣查其源码),最终还是转成坐标点:
public void touch(By selector, TouchPressType type)
{
Point p = getElementCenter(selector);
mDevice.getImpl().touch(p.x, p.y, type);
}

HierarchyViewer里面的Visible用的是ViewNode,EasyMonkeyDevice用得是id,最终还是转成ViewNode:

public boolean visible(By selector)
{
ViewNode node = selector.findView(mHierarchyViewer);
return mHierarchyViewer.visible(node);
}

所以本文应该除了给出API的实践之外还应该把每个API和其与MonkeyDevice和HierarchyViewer的API所对应的API给列出来做一个对应的Map,方便我们参考。

 
实践中我们还是用SDK自带的NotePad APK,假设已经有一个Note存在的情况下,通过以下步骤来走一遍EasyMonkeyDevice的所有API:
  • 使用MonkeyDevice对象实例化EasyMonkeyDevice
  • 通过ID Touch一个Note
  • 获得进入NoteEditor activity后的WindowId并验证是否正确
  • 通过ID检查Note的内容这个EditText是否存在和可见
  • 通过Note的ID获得Text
  • 通过Note的ID Type进新Text
  • 通过Note的ID获得Location
以下是我们操作过程中会看到的两个Activity的截图,先贴上来给大家对以上步骤有一个感性认识,最后我会贴出实践验证性代码。
NotesList Activity截图:
NoteEditor Activity截图:
 

2. EaysyMonkeyDevice API List and Sample

EasyMonkeyDevice是在MonkeyDevice和HierarchyViewer的基础上出来的一个类,按照本人的理解,主要增加的功能就是:

  • 在MonkeyDevice和HierarchyViewer的基础上针对部分API增加了对控件ID的支持以操作控件
以下是个人整理的列表:尝试对所有的API进行一个描述和示例Demo

Return

EasyMonkeyDevice

Demo

Comment

EasyMonkeyDevice(MonkeyDevice device) Use Monkey device to construct an EasyMonkeyDevice object, note that it would instantiate a HierarchyViewer member by device within this constructor  device = MonkeyRunner.waitForConnection()   eDevice=EasyMonkeyDevice(device) Constructor

Void

touch(By selector,TouchPressType type) Sends a touch event specified by ‘type’ to the screen location specified by ‘by’  触摸点击主窗口:#Step 1: try touching on the first note eDevice.touch(By.id('id/text1'),               MonkeyDevice.DOWN_AND_UP) 触摸弹出框或Menu Options会失败: MonkeyRunner.sleep(2) print 'Show Menu Options' device.press('KEYCODE_MENU',              MonkeyDevice.DOWN_AND_UP);   MonkeyRunner.sleep(3) print 'Press on the menu entry of \  \"Add note\"' eDevice.touch(By.id('id/title'),                MonkeyDevice.DOWN)   参数By实际上只有By.ID,从 其源码可以看 出来; type参数跟 MonkeyDevice 一样就那几个 DOWN/UP之类的   根据个人实践 和网上评论, 对系统菜单和 弹出框的支持 有问题

Void

type(By selector, String text)Types a string into the specified object  #Step 5: setText eDevice.type(By.id(noteId), 'New')  

Boolean

exists(By selector)Checks if the specified object exists.  #Step3: is note EditText exist? noteId = 'id/note' if True == eDevice.exists(By.id(noteId)):     print 'Note exist' else:     print 'Note not found!'     exit(2)  

Boolean

visible(By selector)Checks if the specified object is visible.  #Step4: is note EditText visible? if True == eDevice.visible(By.id(noteId)):     print 'Note is visible' else:     print 'Note is invisible'     exit(3)  

String

getText(By selector)Obtain the text in the selected input box.  #Step 4: getText text = eDevice.getText(By.id(noteId)) print 'Note text:',text.encode('utf-8')  

String

getFocusedWindowId()Gets the id of the focused window. returns = "The symbolic id of the focused window or None."  #Step 2: Get the window ID winId = 'com.example.android.notepad/\     com.example.android.notepad.NoteEditor' #Need to sleep a while till ready MonkeyRunner.sleep(3) winId = eDevice.getFocusedWindowId() if(winId == winId):     print "Edit Note WinId is:",\         winId.encode('utf-8') else:     print "Failed"     exit(1)      结果跟HierarchyViewer 的 getFocusedWin dowName 返回值一模 一样,所以 猜想WindowID 和WindowName 是同一回事

PyTuple

locate(By selector)Locates the coordinates of the selected object returns = "Tuple containing (x,y,w,h) location and size.")  #Step 6: locate locate = eDevice.locate(By.id(noteId)) print 'Location(x,y,w,h) is:',locate  

3. EasyMonkeyDevice vs MonkeyDevice API Mapping Matrix

这里会列出MonkeyDevice的所有API已经EasyMonkeyDevice与其对应的API,没有去掉冗余是因为方便今后Reference的时候知道EasyMonkeyDevice并不是完全把所有MonkeyDevice的API都进行Wrap的,只有以下两个。下面一章理同。
  • touch:MonkeyDevice通过坐标点touch;EasyMonkeyDevice通过控件ID去touch
  • type:MonkeyDevice往当前focused地方输入;EasyMonkeyDevice往由ID指定控件输入
EasyMonkeyDevice API vs MonkeyDevice API  

MonkeyDevice

EasyMonkeyDevice

Comment

Void broadcastIntent (string uri, string action, string data, string mimetype,  iterable categories dictionary extras,  component component, iterable flags) Broadcasts an Intent to this device, as if the Intent were coming from an application.    
Void drag (tuple start, tuple end, float duration, integer steps) Simulates a drag gesture (touch, hold, and move) on this device's screen.    
ObjectgetProperty (string key)Given the name of a system environment variable, returns its value for this device. The available variable names are listed in the detailed description of this method.    
ObjectgetSystemProperty (string key). The API equivalent of adb shell getprop <key>. This is provided for use by platform developers.    
Void installPackage (string path)Installs the Android application or test package  contained in packageFile onto this device. If the application or test package is already installed, it is replaced.    
Dictionaryinstrument (string className, dictionary args)Runs the specified component under Android instrumentation, and returns the results  in a dictionary whose exact format is dictated by the component being run.  The component must already be present on this device.    
Void press (string name, dictionary type)Sends the key event specified by type to the key specified by keycode.    
Void reboot (string into)Reboots this device into the bootloader specified by bootloadType.    
Void removePackage (string package)Deletes the specified package from this device,  including its data and cache.    
Objectshell (string cmd)Executes an adb shell command and returns the result, if any.    
Void startActivity (string uri, string action, string data, string mimetype, iterable categories  dictionary extras, component component, flags) Starts an Activity on this device by sending an Intent constructed from the supplied arguments.    
MonkeyImagetakeSnapshot()Captures the entire screen buffer of this device, yielding a MonkeyImageobject containing a screen capture of the current display.    
Void touch (integer x, integer y, integer type)Sends a touch event specified by type to the screen location specified by x and y. Void touch(By selector, TouchPressType type)Sends a touch event specified by ‘type’ to the screen location specified  by ‘by’ MonkeyDevice通过坐标点touch;EasyMonkeyDevice通过控件ID去touch
Void type (string message)Sends the characters contained in message to this device, as if they had been typed on the device's keyboard. This is equivalent to calling press() for each keycode in message  using the key event type DOWN_AND_UP. Void type(By selector, String text)Types a string into the specified object MonkeyDevice往当前focused地方输入;EasyMonkeyDevice往由ID指定控件输入
Void wake ()Wakes the screen of this device.    
HierarchyViewer getHierarchyViewer()Get the HierarchyViewer object for the device.    
PyListgetPropertyList()Retrieve the properties that can be queried    
PyListgetViewIdList()Retrieve the view ids for the current application    
MonkeyViewgetViewById(String id)doc = "Obtains the view with the specified id.", args = {"id"}, argDocs = {"The id of the view to retrieve."}, returns = "The view object with the specified id."    
MonkeyViewgetViewByAccessibilityIds(String WinId, String accessId)args = {"windowId", "accessibility id"} argDocs = {"The window id of the view to retrieve.", "The accessibility id of the view to retrieve."}, returns = "The view object with the specified id.")    
MonkeyViewgetRootView()Obtains current root view    
PyListgetViewsByText(String text)Obtains a list of views that contain the specified text.", args = {"text"}, returns = "A list of view objects that contain the specified text.")    

4. EasyMonkeyDevice vs HierarchyViewer Mapping Matrix

EasyMonkeyDevice Wrap了HiearchyViewer 的相应API而得到以下这些API
  • getFocusedWindowId:Wrap了hierarchyviewer的getFocusedWindowName,不再使用ViewNode而使用ID来的获得Window id/Name,其实根据我的实践id/name是同一回事
  • locate:其实就是把HierarchyViewer的getAbsolutePositionOfView和getAbsoluteCenterOfView整合在一起获得起始坐标和Width/Hight,前者获得其实坐标,后者获得中心位置,相减后乘以2就是EasyMonkeyDevice想要的Width/Hight了
  • visible: 同样是把参数由ViewNode改成id
  • getText:同上
EasyMonkeyDevice API vs HierarchViewer API  

HierarchyViewer

EasyMonkeyDevice

Comment

public ViewNode findViewById(String id)

/** * Find a view by id. * @param id id for the view. * @return view with the specified ID, or {@code null} if no view found. */

   
public ViewNode findViewById(String id, ViewNode rootNode)

/** * Find a view by ID, starting from the given root node * @param id ID of the view you're looking for * @param rootNode the ViewNode at which to begin the traversal * @return view with the specified ID, or {@code null} if no view found. */
   
public String getFocusedWindowName()

/** * Gets the window that currently receives the focus. * @return name of the window that currently receives the focus. */

String getFocusedWindowId()Gets the id of the focused window. returns = "The symbolic id of the focused window or None."  
public static Point getAbsolutePositionOfView(ViewNode node)/**
* Gets the absolute x/y position of the view node. * * @param node view node to find position of. * @return point specifying the x/y position of the node. */

PyTuple locate(By selector)Locates the coordinates of the selected object returns = "Tuple containing (x,y,w,h) location and size.")  
public static Point getAbsoluteCenterOfView(ViewNode node)

/** * Gets the absolute x/y center of the specified view node. * * @param node view node to find position of. * @return absolute x/y center of the specified view node. */
public boolean visible(ViewNode node)

/** * Gets the visibility of a given element. * @param selector selector for the view. * @return True if the element is visible. */

boolean visible(By selector)Checks if the specified object is visible.  
public String getText(ViewNode node)

/** * Gets the text of a given element. * * @param selector selector for the view. * @return the text of the given element. */

String getText(By selector)Obtain the text in the selected input box.  

5. EasyMonkeyDevice Standalone API

剩下一个API是没有跟以上的MonkeyDevice和HierarchyViewer有任何对应关系的:
  • visible:通过id检查该控件是否存在,猜想应该是google在代码重构的时候增加的一个方法方便大家判断而已
EasyMonkeyDevice Standalone API  

EasyMonkeDevice

Comment

boolean exists(By selector)Checks if the specified object exists.  

6. 验证性代码

from com.android.monkeyrunner import MonkeyRunner,MonkeyDevice,MonkeyImage
from com.android.monkeyrunner.easy import EasyMonkeyDevice,By
from com.android.chimpchat.hierarchyviewer import HierarchyViewer
from com.android.hierarchyviewerlib.models import ViewNode, Window
from java.awt import Point #from com.android.hierarchyviewerlib.device import #Connect to the target device device = MonkeyRunner.waitForConnection() eDevice=EasyMonkeyDevice(device)
device.startActivity(component="com.example.android.notepad/com.example.android.notepad.NotesList") '''
MonkeyRunner.sleep(2)
print 'Show Menu Options'
device.press('KEYCODE_MENU',
MonkeyDevice.DOWN_AND_UP); MonkeyRunner.sleep(3)
print 'Press on the menu entry of \
\"Add note\"'
eDevice.touch(By.id('id/title'),
MonkeyDevice.DOWN) MonkeyRunner.sleep(2)
device.press('KEYCODE_MENU',
MonkeyDevice.DOWN_AND_UP);
''' #Step 1: try touching on the first note
eDevice.touch(By.id('id/text1'),
MonkeyDevice.DOWN_AND_UP) #Step 2: Get the window ID
winId = 'com.example.android.notepad/\
com.example.android.notepad.NoteEditor'
#Need to sleep a while till ready
MonkeyRunner.sleep(3)
winId = eDevice.getFocusedWindowId()
if(winId == winId):
print "Edit Note WinId is:",\
winId.encode('utf-8')
else:
print "Failed"
exit(1) #Step3: is note EditText exist?
noteId = 'id/note'
if True == eDevice.exists(By.id(noteId)):
print 'Note exist'
else:
print 'Note not found!'
exit(2) #Step4: is note EditText visible?
if True == eDevice.visible(By.id(noteId)):
print 'Note is visible'
else:
print 'Note is invisible'
exit(3) #Step 4: getText
text = eDevice.getText(By.id(noteId))
print 'Note text:',text.encode('utf-8') #Step 5: setText
eDevice.type(By.id(noteId), 'New') #Step 6: locate
locate = eDevice.locate(By.id(noteId))
print 'Location(x,y,w,h) is:',locate

7. EasyMonkeyDevice Source Code for Your Reference

/*jadclipse*/// Decompiled by Jad v1.5.8e. Copyright 2001 Pavel Kouznetsov.

package com.android.monkeyrunner.easy;

import com.android.chimpchat.hierarchyviewer.HierarchyViewer;
import com.android.hierarchyviewerlib.models.ViewNode;
import com.android.monkeyrunner.JythonUtils;
import com.google.common.base.Preconditions;
import org.python.core.*; public class By extends PyObject
implements ClassDictInit
{ public static void classDictInit(PyObject dict)
{
JythonUtils.convertDocAnnotationsForClass(com/android/monkeyrunner/easy/By, dict);
} By(String id)
{
this.id = id;
} public static By id(PyObject args[], String kws[])
{
ArgParser ap = JythonUtils.createArgParser(args, kws);
Preconditions.checkNotNull(ap);
String id = ap.getString(0);
return new By(id);
} public static By id(String id)
{
return new By(id);
} public ViewNode findView(HierarchyViewer viewer)
{
return viewer.findViewById(id);
} private String id;
} /*
DECOMPILATION REPORT Decompiled from: D:\Projects\Workspace\JarPackages\monkeyrunner.jar
Total time: 69 ms
Jad reported messages/errors:
The class file version is 50.0 (only 45.3, 46.0 and 47.0 are supported)
Exit status: 0
Caught exceptions:
*/

8. By Class Source Code for Your Better Reference

/*jadclipse*/// Decompiled by Jad v1.5.8e. Copyright 2001 Pavel Kouznetsov.

package com.android.monkeyrunner.easy;

import com.android.chimpchat.core.IChimpDevice;
import com.android.chimpchat.core.TouchPressType;
import com.android.chimpchat.hierarchyviewer.HierarchyViewer;
import com.android.hierarchyviewerlib.models.ViewNode;
import com.android.monkeyrunner.JythonUtils;
import com.android.monkeyrunner.MonkeyDevice;
import com.google.common.base.Preconditions;
import java.util.Set;
import org.eclipse.swt.graphics.Point;
import org.python.core.*; // Referenced classes of package com.android.monkeyrunner.easy:
// By public class EasyMonkeyDevice extends PyObject
implements ClassDictInit
{ public static void classDictInit(PyObject dict)
{
JythonUtils.convertDocAnnotationsForClass(com/android/monkeyrunner/easy/EasyMonkeyDevice, dict);
} public EasyMonkeyDevice(MonkeyDevice device)
{
mDevice = device;
mHierarchyViewer = device.getImpl().getHierarchyViewer();
} public void touch(PyObject args[], String kws[])
{
ArgParser ap = JythonUtils.createArgParser(args, kws);
Preconditions.checkNotNull(ap);
By selector = getSelector(ap, 0);
String tmpType = ap.getString(1);
TouchPressType type = TouchPressType.fromIdentifier(tmpType);
Preconditions.checkNotNull(type, (new StringBuilder()).append("Invalid touch type: ").append(tmpType).toString());
touch(selector, type);
} public void touch(By selector, TouchPressType type)
{
Point p = getElementCenter(selector);
mDevice.getImpl().touch(p.x, p.y, type);
} public void type(PyObject args[], String kws[])
{
ArgParser ap = JythonUtils.createArgParser(args, kws);
Preconditions.checkNotNull(ap);
By selector = getSelector(ap, 0);
String text = ap.getString(1);
type(selector, text);
} public void type(By selector, String text)
{
Point p = getElementCenter(selector);
mDevice.getImpl().touch(p.x, p.y, TouchPressType.DOWN_AND_UP);
mDevice.getImpl().type(text);
} public PyTuple locate(PyObject args[], String kws[])
{
ArgParser ap = JythonUtils.createArgParser(args, kws);
Preconditions.checkNotNull(ap);
By selector = getSelector(ap, 0);
ViewNode node = selector.findView(mHierarchyViewer);
Point p = HierarchyViewer.getAbsolutePositionOfView(node);
PyTuple tuple = new PyTuple(new PyObject[] {
new PyInteger(p.x), new PyInteger(p.y), new PyInteger(node.width), new PyInteger(node.height)
});
return tuple;
} public boolean exists(PyObject args[], String kws[])
{
ArgParser ap = JythonUtils.createArgParser(args, kws);
Preconditions.checkNotNull(ap);
By selector = getSelector(ap, 0);
return exists(selector);
} public boolean exists(By selector)
{
ViewNode node = selector.findView(mHierarchyViewer);
return node != null;
} public boolean visible(PyObject args[], String kws[])
{
ArgParser ap = JythonUtils.createArgParser(args, kws);
Preconditions.checkNotNull(ap);
By selector = getSelector(ap, 0);
return visible(selector);
} public boolean visible(By selector)
{
ViewNode node = selector.findView(mHierarchyViewer);
return mHierarchyViewer.visible(node);
} public String getText(PyObject args[], String kws[])
{
ArgParser ap = JythonUtils.createArgParser(args, kws);
Preconditions.checkNotNull(ap);
By selector = getSelector(ap, 0);
return getText(selector);
} public String getText(By selector)
{
ViewNode node = selector.findView(mHierarchyViewer);
return mHierarchyViewer.getText(node);
} public String getFocusedWindowId(PyObject args[], String kws[])
{
return getFocusedWindowId();
} public String getFocusedWindowId()
{
return mHierarchyViewer.getFocusedWindowName();
} public PyObject __findattr_ex__(String name)
{
if(!EXPORTED_METHODS.contains(name))
return mDevice.__findattr_ex__(name);
else
return super.__findattr_ex__(name);
} private By getSelector(ArgParser ap, int i)
{
return (By)ap.getPyObject(i).__tojava__(com/android/monkeyrunner/easy/By);
} private Point getElementCenter(By selector)
{
ViewNode node = selector.findView(mHierarchyViewer);
if(node == null)
{
throw new PyException(Py.ValueError, String.format("View not found: %s", new Object[] {
selector
}));
} else
{
Point p = HierarchyViewer.getAbsoluteCenterOfView(node);
return p;
}
} private MonkeyDevice mDevice;
private HierarchyViewer mHierarchyViewer;
private static final Set EXPORTED_METHODS = JythonUtils.getMethodNames(com/android/monkeyrunner/easy/EasyMonkeyDevice); } /*
DECOMPILATION REPORT Decompiled from: D:\Projects\Workspace\JarPackages\monkeyrunner.jar
Total time: 920 ms
Jad reported messages/errors:
The class file version is 50.0 (only 45.3, 46.0 and 47.0 are supported)
Exit status: 0
Caught exceptions:
*/
作者 自主博客 微信服务号及扫描码 CSDN
天地会珠海分舵 http://techgogogo.com 服务号:TechGoGoGo扫描码: http://blog.csdn.net/zhubaitian

EasyMonkeyDevice vs MonkeyDevice&HierarchyViewer API Mapping Matrix的更多相关文章

  1. EasyMonkeyDevice vs MonkeyDevice&amp;HierarchyViewer API Mapping Matrix

    1. 前言 本来这次文章的title是写成和前几篇类似的<EasyMonkeyDevice API实践全记录>,内容也打算把每一个API的实践和建议给记录下来,但后来想了下认为这样子并非最 ...

  2. ElasticSearch Index API && Mapping

    ElasticSearch  NEST Client 操作Index var indexName="twitter"; var deleteIndexResponse = clie ...

  3. 开启真机的View Server引入HierarchyViewer/By写monkeyrunner自动化测试脚本

    其实相关文章网上也有不少了,不过在真机上开启View Server的中文文章好像只有一篇,前段时间按照这篇文章的内容,并结合英文源文去hack我的Nexus S(4.1.2)也走了一点弯路.现在总结一 ...

  4. Elasticsearch从0.90(0.90.x)到1.2(1.x)API的变化-二

    本文为官方文档的译文加个人理解.作者翻译时,elasticsearch(下面简称es)的版本为1.2.2. 请支持原创:http://www.cnblogs.com/donlianli/p/38367 ...

  5. web2.0最全的国外API应用集合

    web2.0最全的国外API应用集合 原文地址:http://www.buguat.com/post/98.html 2.0时代,越来越多的API被大家广泛应用,如果你还不了解API是何物,请看这里的 ...

  6. Google Maps API Web Services

    原文:Google Maps API Web Services 摘自:https://developers.google.com/maps/documentation/webservices/ Goo ...

  7. Google Maps API的使用

    之前在学习了简单的API调用后,查看了几个知名网站的API调用方法,发现Google的API调用还是相对比较简单的.下面就从API key的获取.googlemaps的安装,再到实际使用做一下说明. ...

  8. Web API 2 自定义默认Identity Table Name

    One of the first issues you will likely encounter when getting started with ASP.NET Identity centers ...

  9. Docker Engine SDKs and API 的开发1

    Develop with Docker Engine SDKs and API Docker provides an API for interacting with the Docker daemo ...

随机推荐

  1. 【iOS7一些总结】9、与列表显示(在):列表显示UITableView

    列表显示,顾名思义它是在一个列表视图的形式显示在屏幕上的数据的内容.于ios在列表视图UITableView达到.这个类在实际应用中频繁,是很easy理解.这里将UITableView的主要使用方法总 ...

  2. POJ1149 PIGS 【最大流量】

    PIGS Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 16555   Accepted: 7416 Description ...

  3. 怎么样ubuntu 64 11.04 在执行32位程序

    上网一查非常多的信息,头发上的今天ubuntu 64 11.04 在执行32位程序安装ia32-libs包,可执行例如,下面的命令.但提示无法安装 apt-get install ia32-libs ...

  4. 【源代码】Set集合源代码剖析

    注:下面源代码基于jdk1.7.0_11 Set集合事实上是对Map集合的封装,Map集合存储的是键值对,那么我们将值隐藏,不向外界暴露,这样就形成了Set集合. 相应Map集合的两个非常重要的实现H ...

  5. 解决Activity启动黑屏和设置android:windowIsTranslucent不兼容activity切换动画的问题

    在该项目中遇到开Activity之后,黑屏问题,解决的办法是在网上通过设置发现theme和style特性,可以实现. http://www.cnblogs.com/sunzn/p/3407078.ht ...

  6. Ubuntu14.04 工作区设置

    记ubuntu您可以切换工作区,但我按住 Ctrl+Alt+方向键 交换器,有没有反应,在这样的使用切换啊. 原来Ubuntu14.04默认并没有开启,仅仅须要设置一下就OK了. 1.打开系统设置.外 ...

  7. win8 iis7/iis8 安装、卸载、设置方法

    原文:win8 iis7/iis8 安装.卸载.设置方法 一.安装 自从升级到Win8之后,之前使用已经趋于熟悉的iis7.0被取而代之的是iis8.0,那么安装和获取方法也就产生的略微的变化,为了避 ...

  8. Java内部类详解(转)

    说起内部类这个词,想必很多人都不陌生,但是又会觉得不熟悉.原因是平时编写代码时可能用到的场景不多,用得最多的是在有事件监听的情况下,并且即使用到也很少去总结内部类的用法.今天我们就来一探究竟.下面是本 ...

  9. java求最大公约数(分解质因数)

    下面是四种用java语言编程实现的求最大公约数的方法: package gcd; import java.util.ArrayList; import java.util.List; public c ...

  10. 彩色图像上执行Mean Shift迭代搜索目标 ,维加权直方图 + 巴氏系数 + Mean Shift迭代

    今天要给大家分享的是: 在彩色图像上进行Mean Shift迭代搜索目标 二维加权直方图+巴氏系数+Mean Shift迭代 关于 加权直方图.巴氏系数.Mean Shift迭代 这三者之间的关系请大 ...