[转]忽略PNG透明区域的事件(AS/Flash)

本文介绍了一种使用AS3处理PNG图像透明区域点击事件的方法,通过自定义PNGLoader类来绘制非透明像素区域,从而避免了透明部分响应鼠标事件的问题。
[url]http://l4cd.net/blog/post-ignore-the-events-of-png-transparency.html[/url]


此文出现源于忽略PNG透明区域的事件(Flex)...
下面是纯as的实现..用的是Loader..帮群里的朋友写的实例
详情的思路什么的就不说了..看上面的地址

效果(左边的PNGLoader加截的png忽略透明,右边的为普通Loader):




package net.l4cd.display
{
import flash.display.BitmapData;
import flash.display.Loader;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.events.ProgressEvent;
import flash.geom.Matrix;
import flash.net.URLRequest;
import flash.system.LoaderContext;
import flash.utils.ByteArray;

/**
* PNGLoader,主要解决png图片透明像素处事件的问题
* @author L4cd.Net
*
*/
public class PNGLoader extends Sprite
{
private var loader:Loader = new Loader();
private var hit:Sprite = new Sprite();
public function PNGLoader()
{
addChild(loader);
addChild(hit);
hit.visible = false;
hit.mouseEnabled = false;
mouseChildren = false;
hitArea = hit;
loader.contentLoaderInfo.addEventListener(Event.COMPLETE,complete);
loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR,error);
loader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS,progress);
}
private function complete(e:Event):void
{
dispatchEvent(e);
update();
}
private function error(e:IOErrorEvent):void
{
dispatchEvent(e);
}
private function progress(e:ProgressEvent):void
{
dispatchEvent(e);
}
public function load(request:URLRequest,context:LoaderContext=null):void
{
loader.load(request,context);
clear();
}
public function loadBytes(bytes:ByteArray,context:LoaderContext=null):void
{
loader.loadBytes(bytes,context);
clear();
}
public function unload():void
{
loader.unload();
clear();
}
public function close():void
{
loader.close();
clear();
}
private function clear():void
{
hit.graphics.clear();
}
private function update():void
{
if(!loader.content)return;
var bit:BitmapData = new BitmapData(loader.width,loader.height,true,0x00000000);
bit.draw(loader);
//重绘图象到bit
clear();
hit.graphics.beginFill(0);
for(var x:uint=0;x<bit.width;x++)
{
for(var y:uint=0;y<bit.height;y++)
{
if(bit.getPixel32(x,y))hit.graphics.drawRect(x,y,1,1);
}
}
//以graphics画出bit的无透明区域
hit.graphics.endFill();
}
}
}




package
{
import flash.display.Loader;
import flash.display.Sprite;
import flash.events.MouseEvent;
import flash.filters.GlowFilter;
import flash.net.URLRequest;

import net.l4cd.display.PNGLoader;


[SWF(width="600",height="400")]
/**
* PNGLoaderExample
* @author L4cd.Net
*
*/
public class PNGLoaderExample extends Sprite
{
public function PNGLoaderExample()
{
var pl:PNGLoader = new PNGLoader();
pl.load(new URLRequest("10020601.png"));
addChild(pl);
pl.y = 20;
pl.addEventListener(MouseEvent.ROLL_OUT,o);
pl.addEventListener(MouseEvent.ROLL_OVER,o);

var ld:Loader = new Loader();
ld.load(new URLRequest("10020601.png"));
addChild(ld);
ld.x = 320;
ld.y = 20;
ld.addEventListener(MouseEvent.ROLL_OUT,o);
ld.addEventListener(MouseEvent.ROLL_OVER,o);


graphics.lineStyle(1);
graphics.drawRect(20,20,250,250);

graphics.drawRect(320,20,250,250);
}
private function o(e:MouseEvent):void
{
e.target.filters = (e.type == MouseEvent.ROLL_OVER)?[new GlowFilter()]:[];
}
}
}


现在新生成的方法如下: class FlashDetector: def __init__(self): # 初始化事件存储列表 self.flash_events_list = [] def record_flash_event(self, area_type, diff_value, app_name=None): """记录闪屏事件到列表""" timestamp = datetime.now().strftime("%H:%M:%S.%f")[:-3] event = { "time": timestamp, "type": area_type, "diff": diff_value, "app": app_name } self.flash_events_list.append(event) print(f"[闪屏] {timestamp} | 区域: {area_type} | 差异: {diff_value:.1f}") def flash_events(self, time_window=1.0): """ 统计指定时间窗口内的闪屏事件 :param time_window: 时间窗口长度(秒) :return: 事件数量及最后事件类型 """ now = datetime.now() count = 0 last_type = None for event in self.flash_events_list: # 正确解析时间字符串 try: event_time = datetime.strptime(event[&#39;time&#39;], "%H:%M:%S.%f") except ValueError: # 处理毫秒部分缺失的情况 event_time = datetime.strptime(event[&#39;time&#39;], "%H:%M:%S") time_diff = (now - event_time).total_seconds() if time_diff <= time_window: count += 1 last_type = event[&#39;type&#39;] return { &#39;count&#39;: count, &#39;last_type&#39;: last_type } @property def last_type(self): """获取最新事件类型""" return self.flash_events_list[-1][&#39;type&#39;] if self.flash_events_list else None def count_recent(self, time_window): """快捷方法:统计近期事件数量""" return self.flash_events(time_window)[&#39;count&#39;] class AdaptiveFlashDetector: def __init__(self): # 创建闪屏检测器实例 self.flash_events = FlashDetector() # 关键修改:使用对象而非方法 def check_flash_adaptive( self, monitor_idx=0, base_threshold=25, # 基础差异阈值 fps=30, # 检测帧率 flash_threshold=1, # 闪屏计数阈值 app_name=None, min_ui_area=0.2, # 最小UI区域占比要求 video_motion_weight=0.5, # 视频运动补偿系数 color_deviation_threshold=40 # 颜色异常阈值 ): # 初始化 sct = mss.mss() monitor = sct.monitors[monitor_idx] # 正确捕获屏幕并换为numpy数组 sct_img = sct.grab(monitor) prev_frame = np.array(sct_img) # 解决sct_img类型警告 frame_history = [prev_frame.copy()] # 存储历史帧 detected = False while True: # 捕获屏幕并确保换为ndarray sct_img = sct.grab(monitor) curr_frame = np.array(sct_img) # 解决类型警告 # 1. 区域类型识别 diff_map = cv2.absdiff(prev_frame, curr_frame) gray_diff = cv2.cvtColor(diff_map, cv2.COLOR_BGR2GRAY) _, motion_mask = cv2.threshold(gray_diff, 15, 255, cv2.THRESH_BINARY) # 计算区域比例 video_area_ratio = np.mean(motion_mask > 0) ui_area_ratio = 1 - video_area_ratio # 2. 双模式检测 ## UI区域检测 if ui_area_ratio > min_ui_area: ui_mask = cv2.bitwise_not(motion_mask) ui_diff = np.mean(diff_map[ui_mask > 0]) ui_threshold = base_threshold * (1 + video_area_ratio * video_motion_weight) if ui_diff > ui_threshold: # 使用对象方法记录事件 self.flash_events.record_flash_event("UI", ui_diff, app_name) ## 视频区域检测 if video_area_ratio > 0.3: motion_continuity = self._calculate_motion_continuity(frame_history[-5:]) color_dev = self._check_color_deviation(curr_frame, prev_frame) video_diff = np.mean(diff_map[motion_mask > 0]) video_threshold = base_threshold * 2 if (video_diff > video_threshold and color_dev > color_deviation_threshold and motion_continuity < 0.7): # 使用对象方法记录事件 self.flash_events.record_flash_event("VIDEO", video_diff, app_name) # 3. 闪屏事件聚合 - 正确调用对象方法 if self.flash_events.count_recent(1.0) >= flash_threshold: print(f"🔥 检测到闪屏异常! 类型: {self.flash_events.last_type}") detected = True break # 更新帧历史 frame_history.append(curr_frame.copy()) if len(frame_history) > 10: frame_history.pop(0) prev_frame = curr_frame.copy() # 退出检测 if cv2.waitKey(int(1000 / fps)) & 0xFF == ord(&#39;q&#39;): break cv2.destroyAllWindows() sct.close() return detected def _calculate_motion_continuity(self, frame_seq): """计算视频运动连续性(0-1)""" if len(frame_seq) < 3: return 1.0 # 计算连续帧之间的运动相关性 motions = [] for i in range(1, len(frame_seq)): diff = cv2.absdiff(frame_seq[i], frame_seq[i - 1]) motions.append(np.mean(diff)) # 计算运动变化的一致性 motion_changes = np.abs(np.diff(motions)) continuity = 1 - np.mean(motion_changes) / np.mean(motions) return max(0, min(1, continuity)) def _check_color_deviation(self, curr_frame, prev_frame): """检测颜色异常(如全屏变绿/变红)""" # 换到HSV空间检测色调突变 curr_hsv = cv2.cvtColor(curr_frame, cv2.COLOR_BGR2HSV) prev_hsv = cv2.cvtColor(prev_frame, cv2.COLOR_BGR2HSV) # 计算色调差异 hue_diff = np.abs(curr_hsv[:, :, 0].astype(int) - prev_hsv[:, :, 0].astype(int)) hue_diff[hue_diff > 90] = 180 - hue_diff[hue_diff > 90] # 处理色调环绕 return np.mean(hue_diff) 但是方法中np.array(sct_img)的sct_img高亮置灰提示Expected type &#39;ndarray | Iterable | int | float&#39;, got &#39;ScreenShot&#39; instead
最新发布
10-14
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值