action,一切从动作开始

本文介绍了一种在项目开发中使用Action模式来封装业务逻辑的方法。通过创建IAction接口和Action类,实现了业务流程的抽象和复用。此外,还提供了一个ActionsProxy类来顺序执行多个Action。
在一年多的项目开发里,我经常会遇到这种情况:每当处理一个业务逻辑,都会创建一个独立的事件类来发送成功或失败执行的事件。后来,接触了一些有关设计模式知识,我就独立写了一个公共类来抽象出业务逻辑,那就是action,可以理解为动作、命令。有了这个类后,做项目时就顺畅多了,但凡是涉及到业务逻辑的,我就用action来封装它。
在创建action前,遵循面向接口编程的原则,我首先创建了一个IAction接口类:
代码:
/**
*动作(命令)接口
*/
package sunnyluo.action
{
import flash.events.IEventDispatcher;

public interface IAction extends IEventDispatcher
{
function execute(event:ActionEvent = null):void; //执行动作
function getActionName():String; //获取动作名称
function actionCompleteHandler(data_:* = null):void; //动作完成
function actionErrorHandler(data_:* = null):void; //动作失败
function destroy():void; //销毁动作
}
}

然后创建Action类,让它实现IAction接口:
代码:
/**
*定义一个动作
*/
package sunnyluo.action
{
import flash.events.EventDispatcher;
import flash.events.TimerEvent;
import flash.utils.Timer;

[Event(name="actionComplete", type="sunnyluo.action.ActionEvent")]
[Event(name="actionError", type="sunnyluo.action.ActionEvent")]

public class Action extends EventDispatcher implements IAction
{
protected var _actionName:String = ""; //动作名称

protected var _liveTimer:Timer; //动作计时器
protected var _timeToLive:Number = 0.0; //动作生命时间

public function Action(name_:String = "")
{
_actionName = name_;
}

/* 开始执行动作 */
public function execute(event:ActionEvent = null):void
{
}

/* 获取动作名称 */
public function getActionName():String
{
return this._actionName;
}

/* 发送执行动作完成事件 */
public function actionCompleteHandler(data_:* = null):void
{
removeLiveTimer();
this.dispatchEvent(new ActionEvent(ActionEvent.ACTION_COMPLETE, data_));
}

/* 发送执行动作错误事件 */
public function actionErrorHandler(data_:* = null):void
{
removeLiveTimer();
this.dispatchEvent(new ActionEvent(ActionEvent.ACTION_ERROR, data_));
if(_actionName)
{
trace("action error:" + this._actionName);
}
}

/* 开始动作计时 */
public function startLiveTimer():void
{
if(_timeToLive <= 0.0)
{
return;
}
_liveTimer = new Timer(_timeToLive, 1);
_liveTimer.addEventListener(TimerEvent.TIMER_COMPLETE, onLiveTimerComplete);
_liveTimer.start();
}

/* 动作计时完成,发送动作执行错误事件,并带上超时参数 */
protected function onLiveTimerComplete(event:TimerEvent):void
{
this.actionErrorHandler(ActionEvent.ACTION_TIME_OUT);
}

/* 移除动作计时 */
protected function removeLiveTimer():void
{
if(_liveTimer)
{
_liveTimer.removeEventListener(TimerEvent.TIMER_COMPLETE, onLiveTimerComplete);
_liveTimer.stop();
_liveTimer = null;
}
}

/* 设置动作生命时间 */
public function set timeToLive(value:Number):void
{
_timeToLive = value;
}

/* 销毁动作 */
public function destroy():void
{
removeLiveTimer();
}

}
}

还有创建了一个继承于Action的ActionsProxy类,用于顺序执行多个Action动作:
代码:
/**
* 执行一系列的动作
*/
package sunnyluo.action
{
import flash.events.Event;

[Event(name="actionsOneResult", type="sunnyluo.action.ActionEvent")]
public class ActionsProxy extends Action
{
public var isAlwaysExecute:Boolean = false; //是否一直执行动作(不管某个动作发生错误)

protected var _actions:Array = []; //动作数组
protected var _curAction:IAction; //当前执行的动作
protected var _actionIndex:int = -1; //当前执行的动作序号
protected var _data:* = new Object();

protected var _stoped:Boolean = false;//是否停止动作执行

public function ActionsProxy(name_:String = "")
{
super(name_);
}

//开始执行一系列动作
override public function execute(event:ActionEvent = null):void
{
if(! _actions || _actions.length == 0)
{
this.actionCompleteHandler();
return;
}
executeOneAction();
}

/* 添加一个动作 */
public function addOneAction(action_:IAction):void
{
if(action_)
{
_actions.push(action_);
}
}

/* 添加一组动作 */
public function addActions(actions_:Array):void
{
_actions = _actions.concat(actions_);
}

/**
* 执行一个action 操作
*
*/
protected function executeOneAction():void
{
_actionIndex ++;
if(_actionIndex >= _actions.length)
{
completeAllHandler();
return;
}
var __action:IAction = _actions[_actionIndex];
if(! __action)
{
executeOneAction();
return;
}
_curAction = __action;
ActionUtil.addActionHandler(_curAction, onActionResult, onActionResult);
__action.execute();

}
/**
* 执行一个动作后的处理,
* 判断动作是否执行正确,是否需要执行新的操作
* @param event
*
*/
protected function onActionResult(event:ActionEvent):void
{
if(event &&(event.type == ActionEvent.ACTION_ERROR))
{
var __errorStr:String = (event.target as IAction).getActionName();
trace("action error:", __errorStr);
//动作执行错误时,判断是否继续执行其它动作
if(! isAlwaysExecute)
{
this.actionErrorHandler();
return;
}
}
completeOneHandler();
}

/* 移除当前动作 */
protected function removeCurAction():void
{
if(_curAction)
{
ActionUtil.removeActionHandler(_curAction);
_curAction.destroy();
_curAction = null;
}
}

/* 完成一个动作后执行 */
protected function completeOneHandler():void
{
if(! _stoped)
{
//发送一个动作执行完成的事件
this.dispatchEvent(new ActionEvent(ActionEvent.ACTIONS_ONE_RESULT, event));
removeCurAction();
executeOneAction();
}

}

/* 完成所有动作后执行 */
protected function completeAllHandler():void
{
super.actionCompleteHandler(_data);
}

//销毁动作
override public function destroy():void
{
_stoped = true;
removeCurAction();
_actions = null;
}

/**
* 获取动作数组
* @return
*
*/
public function getActions():Array{
return _actions;
}

/**
* 获取当前正在执行的动作的序号
* @return
*
*/
public function getCurActionIndex():int
{
return _actionIndex;
}

/**
* 获取动作数组长度(动作个数)
* @return
*
*/
public function getActionsLength():int
{
return _actions ? _actions.length : 0;
}

}
}

ActionEvent动作事件,用来统一发送动作执行成功或失败事件:
代码:
/**
* 动作事件
*/
package sunnyluo.action
{
import flash.events.Event;

public class ActionEvent extends Event
{
public static const ACTION_COMPLETE:String = "actionComplete"; //执行动作成功事件
public static const ACTION_ERROR:String = "actionError"; //执行动作错误事件

public static const ACTION_TIME_OUT:String = "actionTimeOut"; //执行动作超时

public static const ACTIONS_ONE_RESULT:String = "actionsOneResult"; //执行多个动作时,有一个执行结果(成功或失败)事件

public var data : *; //动作数据

public function ActionEvent(type:String, data_:* = null, bubbles:Boolean=false, cancelable:Boolean=false)
{
data = data_;
super(type, bubbles, cancelable);
}
}
}

ActionUtil是动作工具类,负责处理ActionEvent事件:
代码:
/**
* 动作的工具类
*/
package sunnyluo.action
{
import flash.utils.Dictionary;

public class ActionUtil
{
private static var _actionLis:Dictionary = new Dictionary(); //记录动作的侦听

public function ActionUtil()
{
}

/**
* 添加动作侦听
* @param action_ 要侦听的动作
* @param completeFunc_ 动作完成时执行的函数
* @param errorFunc_ 动作发生错误时执行的函数
* @return
*
*/
public static function addActionHandler(action_:IAction, completeFunc_:Function = null, errorFunc_:Function = null):IAction
{
action_.addEventListener(ActionEvent.ACTION_COMPLETE, onActionComplete, false, 0, true);
action_.addEventListener(ActionEvent.ACTION_ERROR, onActionError, false, 0, true);
//action_.execute();
_actionLis[action_] = [onActionComplete, onActionError];
return action_;

//动作执行成功处理
function onActionComplete(event: ActionEvent):void
{
removeActionHandler(action_);
if(completeFunc_ != null)
{
completeFunc_(event);
}
}

////动作执行错误处理
function onActionError(event: ActionEvent):void
{
removeActionHandler(action_);
if(errorFunc_ != null)
{
errorFunc_(event);
}
}
}

/* 移除动作的侦听 */
public static function removeActionHandler(action_:IAction):void
{
if(! action_ || ! _actionLis[action_])
{
return;
}
if(action_.hasEventListener(ActionEvent.ACTION_COMPLETE))
{
action_.removeEventListener(ActionEvent.ACTION_COMPLETE, _actionLis[action_][0]);
}
if(action_.hasEventListener(ActionEvent.ACTION_ERROR))
{
action_.removeEventListener(ActionEvent.ACTION_ERROR, _actionLis[action_][1]);
}
delete _actionLis[action_];
}


}
}
### MATLAB中人体动作识别算法的实现 #### 背景介绍 人体动作识别是一项复杂的技术,通常涉及多个阶段的操作流程,包括但不限于数据采集、特征提取以及分类器的设计与训练。MATLAB作为一种强大的科学计算工具,在这一领域提供了丰富的函数库支持。 #### 数据采集 为了进行人体动作识别,首先需要获取高质量的动作数据集。这些数据可以通过摄像头捕捉视频帧并转换成二维坐标点来表示身体的关键部位位置[^2]。例如: ```matlab % 使用VideoReader读取视频文件 videoFile = 'action_video.mp4'; v = VideoReader(videoFile); frameCount = v.NumFrames; for i = 1:frameCount frame = read(v, i); end ``` #### 特征提取 一旦获得了原始图像或者视频序列之后,则需进一步执行特征提取操作以便后续分析能够更加聚焦于有意义的信息之上。一种常见方法就是利用差影法找出运动区域内的变化情况从而确定目标对象所在范围及其动态特性[^1]。 ```matlab function diffImage = computeDifference(currentFrame, previousFrame) grayCurrent = rgb2gray(currentFrame); grayPrevious = rgb2gray(previousFrame); diffImage = abs(double(grayCurrent) - double(grayPrevious)); end ``` #### 姿态估计与关键点定位 接着便是对人体的姿态做出精确评估,并标记出各个关节的具体坐标的环节。这一步骤往往依赖预先训练好的深度学习模型完成自动化检测过程;当然也可以采用传统计算机视觉技巧手动设定阈值等方式近似达成目的[^3]。 ```matlab detector = peopleDetectorACF; [bboxes,scores] = detect(detector,img); person = vision.PeopleDetector(); person.BodyParts = {'Head','ShoulderLeft'}; [~,partsBBoxes] = detectPeopleParts(person,img,... 'BodyPartTypes',{'Head','ShoulderLeft'}); ``` #### 动作分类 最后要做的就是把前面所得到的一切有用信息输入给专门构建用于区分不同种类活动模式的支持向量机(SVM)或者其他类型的监督式学习机制之中去接受检验最终得出结论说当前正在进行哪一类特定形式的身体移动行为。 ```matlab load('trainedSVMModel.mat'); testFeatures = extractHOGFeatures(testImg); predictedLabel = predict(svmModel,testFeatures'); disp(predictedLabel); ``` 以上就是在MATLAB环境下针对人体动作识别整个工作链条上的几个主要组成部分进行了简述说明。每一段代码片段都代表了一个独立的功能模块,实际项目开发过程中可能还需要考虑更多细节方面的问题解决办法才行。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值