知乎上有个帖子发表了可以用安卓扣扣查询某人的出行及作息规律,仿照其思路实现了这个功能。
基本思路是:首先用软件将扣扣界面截图,然后将目的区域进行状态的识别。这里需要用到机器学习的思路,先制作一个状态识别的训练库,然后将每一次的截图信息用训练好的状态分类器进行单次分类,然后将时间和状态信息输出到文本文件。
1. 状态训练库制作
程序是用matlab编写的,首先手动截图(扣扣登陆下ctrl+alt+a)目的区域,得到大量状态图片库,为了让matlab能统一进行处理,需要在PS中将每个图片大小和格式改为一致,示例中为[30,30]像素的png图片:
图一 状态训练库训练图片库命名为Trainingdatas,这里单张图片名称可以乱写无所谓,因为做成训练库需要建立子文件夹,把类别相同的图片放到一起,子文件夹的名称就是分类名,像这样:
图二 制作好的状态训练库在这里,也将测试阶段的测试图做好一个库,所有待识别图片放到一个文件夹命名为Testsample即可。
2. 编写程序进行指定区域截图
分析的对象为了在电脑上实现,用了夜神安卓模拟器登陆手机扣扣作为数据来源。
图三 安卓模拟器状态数据来源仿照网络上寻找到的matlab调用Java实现截图的方法编写了一个属于自己的截图函数TangJietu,该函数能在给定参数[w,h,x,y](宽,高,起点横坐标,起点纵坐标)下截取桌面指定区域的像素图片:
function I = TangJietu(w,h,x,y)
%%调用java接口的截图函数,给定起点坐标和截图大小返回一个三维uint8数组图片数据
% w和h为指定的截图宽度和高度!默认值为(1920,1080)
% x和y为截图起点横、纵坐标!默认值为(1,1),一般可省略
if nargin == 0
x=1;y=1;w=1920;h=1080;
elseif nargin == 2
x=1;y=1;
elseif nargin == 4
else
print('Input error!!')
return;
end
robot = java.awt.Robot();
rectangle = java.awt.Rectangle();
rectangle.x = x;
rectangle.y = y;
rectangle.width = w;
rectangle.height = h;
w = image.getWidth();
h = image.getHeight();
raster = image.getData();
I = zeros(w*h*3,1);
I = raster.getPixels(0,0,w,h,I);
I = uint8(I);
I1 = I(1:3:length(I));
I1 = reshape(I1,w,h);
I2 = I(2:3:length(I));
I2 = reshape(I2,w,h);
I3 = I(3:3:length(I));
I3 = reshape(I3,w,h);
I = uint8(zeros(w,h,3));
I(1:w,1:h,1) = I1;
I(1:w,1:h,2) = I2;
I(1:w,1:h,3) = I3;
I = imrotate(I,-90,'nearest');
I = flipdim(I,2);
这里我不重点学习截图函数是怎么写好,因为是照搬别人的程序稍加修改得到的,这里截图坐标和大小的选择除了参考PS,还可以参考一个叫Colorpix的小软件估计坐标值。
然后下一步是写一个用于训练和分类的函数,这里是照搬了matlab参考页Object Detection and Recognition主题下的Digit Classification Using HOG Features示例写的一个函数Fenlei,作用是将文件夹下的训练库进行分类训练,返回测试库中给定图片的分类状态:
function classlabel = Fenlei()
% 将训练文件夹的数据训练分类,求测试文件夹里面数据的分类情况
% 这个函数写出来的目的就是为了实现单次测试,每次测试一个图片,返回一个分类值
syntheticDir = fullfile('G:\Program\Run\Status\Trainingdatas');
handwrittenDir = fullfile('G:\Program\Run\Status\Testsample');
trainingSet = imageDatastore(syntheticDir, 'IncludeSubfolders', true, 'LabelSource', 'foldernames');
testSet = imageDatastore(handwrittenDir, 'IncludeSubfolders', true, 'LabelSource', 'foldernames');
img = readimage(trainingSet, 1);
[hog_2x2, vis2x2] = extractHOGFeatures(img,'CellSize',[2 2]);
cellSize = [2 2];
hogFeatureSize = length(hog_2x2);
numImages = numel(trainingSet.Files);
trainingFeatures = zeros(numImages, hogFeatureSize, 'single');
for i = 1:numImages
img = readimage(trainingSet, i);
img = rgb2gray(img);
img = imbinarize(img);
trainingFeatures(i, :) = extractHOGFeatures(img, 'CellSize', cellSize);
end
trainingLabels = trainingSet.Labels;
classifier = fitcecoc(trainingFeatures, trainingLabels);
[testFeatures, testLabels] = helperExtractHOGFeaturesFromImageSet(testSet, hogFeatureSize, cellSize);
predictedLabels = predict(classifier, testFeatures);
confMat = confusionmat(testLabels, predictedLabels);
classlabel=sprintf('%s',predictedLabels );
这里示例中采用的将图片的HOG特征进行处理方法十分值得学习。需要注意的是matlab新版本出现的classifical属性,类似于array,输出十分麻烦。这里采用了sprintf将分类结果以string的格式作为函数的输出。接下来就是主体运行脚本Whosnetwork的编写了,主要考虑了每隔一段时间运行一次分类,并将结果规整化输出为txt文本数据:
% 获取某人所处网络状态
clear
clc
close all
tic
i=1;
while (i<1000)
Status=TangJietu(30,30,1800,800);
imshow(Status);
imwrite(Status,'G:\Program\Run\Status\Testsample\status.jpg');
new_Status=Fenlei();
now_time=datestr(now, 'yyyymmddHHMMSS');
datas=[now_time,' ',new_Status]
fid=fopen('G:\Program\Run\Status\Testsample\My_Output.txt','a');
fprintf(fid,'%s;',now_time);
fprintf(fid,'%s\r\n',new_Status);
std=fclose(fid);
i=i+1;
pause(300);
end
toc
这里将文本数据规整化输出的内容十分值得记录,很多场合都需要使用。实际可以将循环周期自己设置,采样间隔自己设置,在调试过程中采取了while 1永真的做法,并且pause(0)实现实时观察输出结果,这个网络状态结果从某方面来讲就代替了用户的行为特征。这样就可以从txt输出文件看到网络状态数据了!实验完成!!
图四 状态数据输出文本结果在这里数据的来源选择了周期性截图,数据的分析采用图片的特征识别SVM分类方法,有机器学习的内在思路在里面,关键是做成了一件事情。在生活节奏无比快的今天,在短期正反馈侵蚀着的今天,如何获取关键信息,如何分析数据的内涵就变得十分重要了。
网友评论