Matlab按照彩色图像去除数据冗余
依据实验结果,确定为对于RGB三个分量,每个分量都做差,然后取二范数,如果其中有一个分量大于0.5,这个结果就保留。这应该是我目前编过的最复杂的Matlab程序了,主要是通过这个程序学习到了matlab结构体的好处,数组和cell在处理大量的数据的时候都太麻烦了。结构体加上数组、cell,才是matlab程序语言设计的保存数据的最好的格式。现在知道了为啥matlab读取视频,保存格式为结构体了。fighting!
1 clear;close all;clc; 2 %% 3 %由于程序运行的时间太长了,保存第一次运行的输出 4 % 程序开始执行 5 % 读取图片文件信息,并按类、视频序号、文件尺寸, 6 % 存到结构体fileInfoPartition中,耗时:291.5183 7 % 8 % 把结构体fileInfoPartition按阈值0.5为分割在结构体fileInfoResult 9 % 共耗时:3601.5324 10 % 11 % 拷贝简化后的数据共花费时间:83.9876 12 % 13 % 拷贝冗余的数据共花费时间:91.4804 14 %由于程序运行的时间太长了,保存第二次运行的输出 15 % 程序开始执行 16 % 读取图片文件信息,并按类、视频序号、文件尺寸, 17 % 存到结构体fileInfoPartition中,耗时:155.2753 18 % 19 % 把结构体fileInfoPartition按阈值0.5为分割在结构体fileInfoResult 20 % 共耗时:3231.6106 21 % 22 % 拷贝简化后的数据共花费时间:72.701 23 % 24 % 拷贝冗余的数据共花费时间:67.6085 25 %由于程序运行的时间太长了,保存第三次运行的输出,增加了vainFlag1后的程序, 26 %原以为会跑的快一点,但好像电脑上运行的程序不同的情况下,这数据也不靠谱 27 % 程序开始执行 28 % 读取图片文件信息,并按类、视频序号、文件尺寸, 29 % 存到结构体fileInfoPartition中,耗时:160.3552 30 % 31 % 把结构体fileInfoPartition按阈值0.5为分割在结构体fileInfoResult 32 % 共耗时:3393.9083 33 % 34 % 拷贝简化后的数据共花费时间:55.5579 35 % 36 % 拷贝冗余的数据共花费时间:83.1088 37 %% 38 %程序如何操作: 39 %把变量pathSource为要处理的图片数据,所在的文件夹,就数字时间码识别而言。就是各个子分类0、1、2上一级文件夹 40 %把变量pathDestination改为处理好数据保存的文件夹 41 %destinationFlag和redundanceFlag分别控制是否保存原始的数据和冗余数据 42 %% 43 %下一步改进: 44 % 45 %% 46 %程序实现的功能 47 %1、根据指定的路径、视频序号和差距系数,挑选出对应相同视频号的相同位置数字的冗余的数据 48 %2、把先前挑选出的原始数据保存在文件夹pathdestination、冗余数据保存在文件夹pathredundance 49 %% 50 %程序中用到的新功能:之前一直没用过结构体,现在用了结构体数组。 51 %程序中用到的之前不清楚的函数如下 52 %1)unique(a):提取数组a中的唯一数据,输出结果按从大到小排序。但发现这只能处理1维数组效果比较好。 53 %多维数组并不会选取不同的数组,而会提取出数组中不同的数字 54 %2)setdiff(a,b):返回在a而不在b中的值,返回的值是按从小到大排列,如果a和b完全相同,则返回一个空矩阵 55 %3)exit('folder',dir):判断文件夹是否存在,存在返回7,不存在返回0.还可以判断文件是否存在之类的。 56 %4)norm(a):矩阵的2范数,求所有项的平方和在开根号 57 %5) 58 %% 59 %变量命名规则: 60 %总路径下一层的文件夹记为dir(directory) 61 %最后一层就是各个文件记为file 62 %% 63 %程序编程思路: 64 %比较冗余数据肯定是挑选出相同视频、相同位置、相同数字的图片(不同位置,也可能存在尺寸一样的情况) 65 %而满足相同视频、相同位置的图片,尺寸肯定是相同的。根据这点可以减少数据的运算量 66 %考虑到真实的数据,好像只能用做差的方差来找相同尺寸的图片直接的差异性 67 tic; 68 disp('程序开始执行'); 69 %%%%%%%%%%%%需要更改的参数%%%%%%%%%%%%%%%%%%%% 70 %要处理的数据的源地址,里面有子文件夹0、1、2...9 71 72 pathSource='C:\Users\Dy\Desktop\彩色视频真实数据\sjz'; 73 74 %保存去冗余后数据的路径 75 76 pathDestination='C:\Users\Dy\Desktop\彩色视频真实数据\sjdr'; 77 78 %是否生成无冗余数据的标志符号,为0,不生成,非0生成 79 80 simplifyFlag=1; 81 82 %是否生成冗余数据的标志符号,为0,不生成,非0生成 83 84 redundanceFlag=1; 85 86 %判断数据,是否冗余的阈值,初步选为0.5 87 88 differentCriterion=0.5; 89 90 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 91 %先读取pathSource文件夹下存在的子文件,保存子文件夹信息。方便后面处理。 92 dirList=dir(pathSource);%读取文件夹列表,这种方式读取会保留原文件.(在结构体中第一个)和上一层目录..(在结构体第二个) 93 countDir=length(dirList);%文件夹个数 94 95 %% 96 %提取出原始数据里面的有用数据保存到结构体中 97 %把文件的全部信息一次性全部先读取到一个结构体数组fileInfoRaw中来 98 % 结构体数字,第一维为类别(相对应子文件夹文件名加1),第二维为图片序号 99 % 结构体数组中有字段 100 % name:图片的名字 101 % videonum:图片来源于那个视频 102 % size:[图片的宽(竖直方向跨度),图片的长度(水平方向跨度)] 103 % dirList=dir(pathSource);%读取文件夹列表,这种方式读取会保留原文件.(在结构体中第一个)和上一层目录..(在结构体第二个) 104 % countDir=length(dirList);%文件夹个数 105 for numDir=3:countDir%先读取数据文件夹pathSource下的子文件夹 106 if(length(dirList(numDir).name)>=2)%根据这个过滤掉在此文件夹可能存在的各种txt文件 107 continue; 108 end 109 fileList=dir([pathSource,'\',dirList(numDir).name]); 110 countFile=length(fileList); 111 for numFile=3:countFile%依次读取所有的文件名 112 %去除图片所属的视频序号 113 tempName=fileList(numFile).name; 114 nameStart=strfind(tempName,'_'); 115 nameEnd=strfind(tempName,'-'); 116 tempVideoOrder=tempName(nameStart+1:nameEnd-1); 117 tempPic=imread([pathSource,'\',dirList(numDir).name,'\',fileList(numFile).name]); 118 %tempSize=size(tempPic);%读取的当前图片的size 119 %要注意提取出来的子文件的名称再加1得到了结构体的数据信息,而numFile是从第3开始的,所以要减2 120 fileInfoRaw(str2double(dirList(numDir).name)+1,numFile-2).name=tempName; 121 fileInfoRaw(str2double(dirList(numDir).name)+1,numFile-2).videonum=str2double(tempVideoOrder); 122 fileInfoRaw(str2double(dirList(numDir).name)+1,numFile-2).size=size(tempPic); 123 end 124 end 125 126 %读取出所有的视频序号 127 %读取第一个子文件中的视频数据(一般而言每个视频肯定都会生成数据0,所以读取0文件夹可以选出所有的视频序号的) 128 [sumClasses,maxFile]=size(fileInfoRaw); 129 videoList(1)={0};%cell中第一项填充一个0方面后续的程序编写。 130 %原本想去除所有的视频序号,然后用unique提取出唯一信息。 131 %但由于视频序号并不是统一规格的长短,所以只能用比较麻烦的方法。 132 % for numFile=1:maxFile 133 % if ~isempty(fileInfoRaw(numFile).videonum) 134 % videoList=[videoList;fileInfoRaw(numFile).videonum]; 135 % end 136 % end 137 %读取第一个结构体,就是子文件夹0中的图片数量,挑选没有重复的数据 138 for numFile=1:maxFile 139 %注意这里的fileInfoRaw(1,numFile),就是指定了子文件夹0中的数据,不能忘记这个1 140 if ~isempty(fileInfoRaw(1,numFile).videonum) 141 countVideo=length(videoList); 142 for tempVideoNum=1:countVideo 143 if videoList{tempVideoNum} == fileInfoRaw(1,numFile).videonum 144 continue; 145 else 146 %一开始没加这行,伤不起呀。必须是比较完videoList中所有的 147 %视频序号都没有相同的视频,才开始往videoList中添加 148 if tempVideoNum == countVideo 149 %下面这种方式,对于cell的操作,每次videoList多生成一行 150 videoList=[videoList;fileInfoRaw(1,numFile).videonum]; 151 end 152 end 153 end 154 end 155 end 156 videoList=videoList(2:end);%删除第一项,得到了要处理的视频序号 157 sumVideo=length(videoList);%统计得到video的总数量 158 159 %由于要记录的信息太多,而又想不到能一步得到很多信息的方法。 160 %所以就把这些东西简单分为一小部分一小部分记录 161 %用二维结构体数组fileInfoSize保存图片的尺寸信息,第一维为类别,第二维为对应于videoList中相同位置的视频 162 %先用tempSize保存某一类,某一视频序号videoList{numVideo}下的所有的尺寸信息, 163 %然后再把这些信息保存到结构体fileInfoSize中 164 %结构体数组中有字段 165 %size:保存着对应于行(类别),列(视频videoList{numVideo})的所有尺寸 166 for numClass=1:sumClasses%对应的类别 167 for numVideo=1:sumVideo%对应的视频序号 168 169 % if numVideo==4 170 % temp=1; 171 % end 172 173 tempSize={[0,0,0]};%必须是cell,才能方便每次统计在某个类别下面对应视频的size总数 174 %下面这个for,就是判断指定类别,指定视频序号的所有尺寸的累加 175 for i=1:maxFile 176 %因为结构体也是按最大尺寸,填充的,所以有一些是空的 177 %先判断,如果是空数据就不进行处理 178 179 % if i==59 180 % temp=1; 181 % end 182 183 if isempty(fileInfoRaw(numClass,i).videonum) 184 break; 185 %一次也就判断指定视频的尺寸,所以下面加入判断是对应的视频才处理 186 elseif videoList{numVideo}==fileInfoRaw(numClass,i).videonum 187 188 countTempSize=length(tempSize); 189 %选取到某一个文件信息,然后用tempSize中的所有尺寸信息和其比较,如果都不相同,在添加到tempSize中 190 for numTempSize=1:countTempSize 191 %先用setdiff判断数组tempSize{numTempSize}和fileInfoRaw(numClass,i).size 192 %是否相同,如果相同则返回空,正好用isempty判断 193 %下面一开始判断两个数组是否相等是只有语句isempty(setdiff(tempSize{numTempSize},fileInfoRaw(numClass,i).size)) 194 %而这个函数为setdiff(a,b)只是返回b中没有的a的值,那么遇到a=[17 17 3] 195 %b=[17 15 3],则setdiff(a,b)返回空,所以用了下面这种加强的判断方法, 196 %[setdiff(a,b),setdiff(b,a)]注意两个数组直接连接用的是逗号 197 %这样就可以两个数组直接是不是相等,完全判断 198 if isempty([setdiff(tempSize{numTempSize},fileInfoRaw(numClass,i).size),setdiff(fileInfoRaw(numClass,i).size,tempSize{numTempSize})]) 199 %一开始这写为continue,这是错误的。因为上面的for是在整个tempSize里面 200 %找是否有相同的,有相同的就停止执行后面的else中的添加功能。 201 %如果改为continue了,反倒成了找tempSize中是否有和当前size中不同的数据 202 %如果有,就加进tempSize中。这相当蛋疼。哎,太菜了。 203 %不过也是之前没写过那么复杂的程序。。。。 204 break; 205 else 206 %又忘了加后面这个判断了,如果是所有的在tempSize中的尺寸都比较完之后 207 %还是没有发现和fileInfoRaw(numClass,i).size相同的数据,才往 208 %tempSize中添加新数据 209 if numTempSize == countTempSize 210 tempSize=[tempSize;fileInfoRaw(numClass,i).size]; 211 end 212 end 213 end 214 end 215 end 216 %上面这个for,就取出了对应类别,对应视频的所有不同的尺寸,由于有个初始的[0,0,0] 217 %所以去掉第一个初始值,从第二个开始 218 tempSize=tempSize(2:end); 219 fileInfoPartition(numClass,numVideo).picSize=tempSize; 220 end 221 end 222 223 %把每个类、每个视频中的所有的尺寸信息保存到了结构体fileInfoSize中, 224 %在结构体fileInfoSize再加入sumSize这个字段来统计,对应结构体下各种多少种size的图像 225 for numClass=1:sumClasses%对应的类别 226 for numVideo=1:sumVideo%对应的视频序号 227 fileInfoPartition(numClass,numVideo).sumSize=size(fileInfoPartition(numClass,numVideo).picSize,1); 228 end 229 end 230 231 %往结构体fileInfoPartition中添加字段nameList 232 %nameList中有sumSize行,分别对应于picSize中各行的尺寸 233 %由于早已经把要处理的信息都保存在结构体fileInforRaw,所以只要读取里面的信息就可以了 234 %[sumClasses,maxFile]=size(fileInfoRaw); 235 %sumVideo=length(videoList);%统计得到video的总数量 236 for numClass=1:sumClasses%对应的类别 237 for numVideo=1:sumVideo%对应的视频序号 238 for numSize=1:fileInfoPartition(numClass,numVideo).sumSize%遍历每个类别对应视频下的所有尺寸数据 239 tempName={'0'};%cell类型,方便统计最后的相同尺寸的文件的数量,可以存放不同类型的数据 240 for numFile=1:maxFile 241 %由于结构体,会规整整个结构体的尺寸,所以要首先判断,当前结构体数字下的内容是否为空 242 if isempty(fileInfoRaw(numClass,numFile).videonum) 243 %按顺序遍历整个结构体中的数据,如果发现空内容,所以当前分类的数据已经、 244 %遍历完,所以break,进入下一个类 245 break; 246 elseif videoList{numVideo}==fileInfoRaw(numClass,numFile).videonum 247 %上面先进行判断是不是属于这个视频的数据 248 %下面判断,是不是属于这个尺寸的数据 249 if isempty([setdiff(fileInfoPartition(numClass,numVideo).picSize{numSize},fileInfoRaw(numClass,numFile).size), ... 250 setdiff(fileInfoRaw(numClass,numFile).size,fileInfoPartition(numClass,numVideo).picSize{numSize})]) 251 tempName=[tempName;fileInfoRaw(numClass,numFile).name]; 252 end 253 end 254 end 255 %上面这个for为在某个类别,对应视频序号,按顺序的某个尺寸遍历完的所有文件名列表 256 tempName=tempName(2:end); 257 %由于打算把计算出来的文件名列表保存按行(对应于结构体中picSize中的尺寸信息) 258 %而这样文件名列表不同行(即不同尺寸)的文件数量是不相等的 259 %对于这种不同维度的数据,直接一行一行操作cell会出错,所以只能一个一个进行添加 260 sumName=length(tempName); 261 for i=1:sumName 262 fileInfoPartition(numClass,numVideo).nameList(numSize,i)=tempName(i); 263 end 264 %想到了反正都算出了了不同类别不同视频不同尺寸的文件数量 265 %那就把这个信息保存到结构体的字段picSizeCount中,每行都对应picSize中文件数量 266 fileInfoPartition(numClass,numVideo).picSizeCount(numSize,1)=sumName; 267 end 268 end 269 end 270 %读取文件信息,并按类、视频序号、文件名尺寸存到结构体fileInfoPartition中 271 disp('读取图片文件信息,并按类、视频序号、文件尺寸,'); 272 disp(['存到结构体fileInfoPartition中,耗时:',num2str(toc)]); 273 274 %% 275 %终于把有用的信息都提取到了结构体fileInfoPartition中,结构体总共有10行(10个类别),n列(n个视频) 276 %结构体有字段: 277 %picSize:对应类(结构体行)和视频(结构体列)的数据的尺寸 278 %sumSize:对应类(结构体行)和视频(结构体列)的数据的各种尺寸的总数 279 %nameList:对应类(结构体行)和视频(结构体列)和对应数据的尺寸(对应于字段picSize的行)的文件名列表 280 %picSizeCount:对应类(结构体行)和视频(结构体列)和对应数据的尺寸(对应于字段picSize的行)的文件总数 281 282 %计划把判断是否冗余,计算好后的数据保存到结构体fileInfoResult中 283 %picSize:对应类(结构体行)和视频(结构体列)的数据的尺寸 284 %sumSize:对应类(结构体行)和视频(结构体列)的数据的各种尺寸的总数 285 %nameList:对应类(结构体行)和视频(结构体列)和对应数据的尺寸(对应于字段picSize的行)的文件名列表 286 %和fileInfoPartition中数据相比是它的两倍的行数,相当于把fileInfoPartition中的每一行拆为两行,奇数行为冗余 287 %偶数行为对应的未冗余 288 %picSizePartitionCount:对应于namelist中各行的数据量 289 290 tic; 291 %先把数据在新建的结构体中完成分割,然后再根据destinationFlag和redundanceFlag确定是否要写入分割的数据 292 %先整体扫描结构体中fileInfoPartition,计算出所有的是否冗余的信息,然后存到fileInfoResult中 293 % pathSource='C:\Users\Dy\Desktop\彩色视频真实数据\val2'; 294 %[sumClasses,maxFile]=size(fileInfoRaw); 295 %sumVideo=length(videoList);%统计得到video的总数量 296 %vainFlag:发现要添加一个vainFlag的标记来,取消掉某一个文件名的重复比较 297 %主要是考虑到每到一个文件名,都要计算后面所有的文件是否重复,这个计算量有点大。 298 %而且如果不添加这个flag,会导致比如重复图片中的最后一个图片会被添加到无冗余数据的列表中 299 for numClass=1:sumClasses%对应的类别 300 for numVideo=1:sumVideo%对应的视频序号 301 302 if numVideo==88 303 temp=1; 304 end 305 306 for numSize=1:fileInfoPartition(numClass,numVideo).sumSize%遍历每个类别对应视频下的所有尺寸数据 307 %把字段picSize和sumSize也补上 308 fileInfoResult(numClass,numVideo).picSize=fileInfoPartition(numClass,numVideo).picSize; 309 fileInfoResult(numClass,numVideo).sumSize=fileInfoPartition(numClass,numVideo).sumSize; 310 %用中间变量nameRedundancyTempList来保存对应类别,视频,尺寸的独特的文件名和冗余文件名 311 nameRedundancyTempList={'0'};%保存对应类别,视频,尺寸的冗余的文件名 312 for numName=1:fileInfoPartition(numClass,numVideo).picSizeCount(numSize)%遍历每个类别对应视频下的对应尺寸的文件的多少 313 %初始化vainFlag,使其每次开始检测一个新的文件的时候,都是1的,后面发现如果是冗余数据,在置为0 314 vainFlag=1; 315 %加入判断条件如果遍历到的文件名,已经保存在nameRedundancyTempList中,那么就不需要进行后续的检查了。直接下一个文件 316 sumRedundancy=length(nameRedundancyTempList); 317 for i=1:sumRedundancy 318 %如果在nameRedundancyTempList中发现了当前处理的文件 319 if strcmp(fileInfoPartition(numClass,numVideo).nameList{numSize,numName},nameRedundancyTempList{i}) 320 vainFlag=0; 321 break;%那么就置vainFlag为0,跳出这个循环,也就不用在进行下面的这个文件的所有操作了。 322 end 323 end 324 %如果在冗余列表中发现已有了这个文件,那么这个文件属于vain,就不用进行下面的计算判断了 325 if vainFlag 326 %从头到尾,遍历整个文件名列表,作为要比较的原始数据 327 nameSource=[pathSource,'\',num2str(numClass-1),'\',fileInfoPartition(numClass,numVideo).nameList{numSize,numName}]; 328 picSource=im2double(imread(nameSource)); 329 %为numName可能的最后一个文件名,没有东西可以比较的情况,增加一个特定的判断 330 %而且必须增加一个这样的判断,因为后面和原始图像相比较的,是它的后面一个图像 331 %那么如果numName是文件名最后一个序列的时候,不加if先排除,for会出错 332 if numName~=fileInfoPartition(numClass,numVideo).picSizeCount(numSize) 333 %一开始也没有发现这个隐藏着的bug,不过好在后来发现了。bug藏的深呀,主要是自己编程经验太少了。这程序设计的逻辑有问题 334 %程序总体设计是,遍历对应尺寸的对应图片,用遍历图片后面的图片和它相比较。如果和它相似,那么说明这是冗余,就把这个图片 335 %放到冗余数据保存的列表nameRedundancyTempList中,然后基准按照遍历不断往后,如果发现当前的基准已经在列表nameRedundancyTempList 336 %那么直接跳过,不执行后面的检验程序,因为已经被判定为冗余的数据,在比较其它的数据是否为冗余这不合理。不符合检验数据的逻辑 337 %但这程序如果没有后面的vainFlag1 338 %将存在一个问题,基准图片按照遍历在不断后移,后面比较的数据为当前基准后面到的所有数据,如果因为前面的基准图片已经被判断为 339 %冗余的数据,后面的基准要不要和这个数据进行比较再次判断它是不是冗余数据 340 %这肯定是不能再次判断的,因为有可能再次是冗余,那么就会再次添加到冗余列表中,造成冗余列表中有重复数据 341 %而非冗余列表虽然是通过和冗余列表中比较数据得到的这对应的文件名列表中,其实并不会造成错误,但是由于 342 %统计对应文件名列表的数据长度的字段picSizePartitionCount中的长度,是根据各个冗余列表文件名的长度和原始的 343 %结构体fileInfoPartition相减得到的,这就会出问题。导致把正确的数据划分到冗余数据中。 344 %所以这个bug是必须改正的。属于程序设计逻辑上存在问题 345 %而这个bug的隐蔽性在于,即使一开始这样两重重复遍历,由于一开始被判定为非冗余的数据和被判定为冗余的数据之间其实有差别的 346 %一般来说这个差别大于阈值,所以后面的数据并不会影响程序的运行,但是存在一种非常特殊的情况 347 %假定一开始的基准数据为a,先被判定为非冗余的数据为b,后面被判定为冗余的数据c。这数据还必须要存在这种顺序的排列(a、b、c) 348 %虽然a和b差距较大。但是c处于a和b中的一种中间状态,与a和b都相似。所以a和b判定的时候,都会把c加到冗余列表中 349 %等于这个bug暴露要满足两个条件,a、b、c按顺序排列,c为a和b的一种中间状态 350 %主要还是程序设计的逻辑不严密,所以现在加入标识符vainFlag1,之前被判定为冗余的数据,就不和被判断为非冗余的数据再次比较了。 351 %被判断为非冗余的数据之和被判定为非冗余的数据相比较。逻辑严密并且节省了运算量 352 for numNameCompare=(numName+1):fileInfoPartition(numClass,numVideo).picSizeCount(numSize) 353 %这其实就类似于之前行的vainFlag=1;及其类似 354 %初始化vainFlag1,使其每次开始一个新的对比文件的时候,都是1的,后面发现这个比较文件如果是冗余数据,再置为0 355 vainFlag1=1; 356 %加入判断条件如果遍历到的文件名,已经保存在nameRedundancyTempList中,那么就不需要进行后续的检查了。直接下一个文件 357 sumRedundancy=length(nameRedundancyTempList); 358 for i=1:sumRedundancy 359 %如果在nameRedundancyTempList中发现了当前处理的文件 360 if strcmp(fileInfoPartition(numClass,numVideo).nameList{numSize,numNameCompare},nameRedundancyTempList{i}) 361 vainFlag1=0; 362 break;%那么就置vainFlag为0,跳出这个循环,也就不用在进行下面的这个文件的所有操作了。 363 end 364 end 365 if vainFlag1 366 nameCompare=[pathSource,'\',num2str(numClass-1),'\',fileInfoPartition(numClass,numVideo).nameList{numSize,numNameCompare}]; 367 picCompare=im2double(imread(nameCompare)); 368 picResult=picSource-picCompare; 369 %做出判断,如果差值里面有一个分量的范数大于0.5,那么就算是和原始图像有差距的图像 370 if norm(picResult(:,:,1))>=differentCriterion || norm(picResult(:,:,2))>=differentCriterion || norm(picResult(:,:,3))>=differentCriterion 371 %那么就算是和原始图像有差距的图像,先不进行处理 372 373 else%如果范数不大于0.5,那么算是相似的图像,这个就可以保存在fileInfoResult的nameList中对应的偶数行中 374 nameRedundancyTempList=[nameRedundancyTempList;fileInfoPartition(numClass,numVideo).nameList{numSize,numNameCompare}]; 375 end 376 end 377 end 378 end 379 end 380 end 381 %在这步,基本就是属于在某个类别、视频、尺寸下,所有的冗余的尺寸尺寸信息都保存在了nameRedundancyTempList,所以用下面的语句把内容,放到偶数nameList中去。 382 nameRedundancyTempList=nameRedundancyTempList(2:end); 383 sumRedundancy=length(nameRedundancyTempList); 384 if 0==sumRedundancy 385 %一开始没想到加这个if。主要是之前的方法忽略了一种极为特殊的情况,那就是如果在某类、某个视频,在某种尺寸下只有两个图片 386 %而且这两个图片是相异的(这种情况也有,也是后来发现程序运行bug,我才想到的) 387 %毕竟图片挑选的时候也是尽量挑选不一样的,视频太短的话,可能会出现这种情况 388 %这种特殊的情况下,nameRedundancyTempList里面没有数据,sumRedundancy=0 389 %则后面往奇数行的namelist中添加文件名的操作没办法实现。所以这个if后面,就是往结构体fileInfoResult 390 %的奇数行添加fileInfoPartition的整个文件名列表 391 for i=1:fileInfoPartition(numClass,numVideo).picSizeCount(numSize) 392 fileInfoResult(numClass,numVideo).nameList(2*numSize-1,i)=fileInfoPartition(numClass,numVideo).nameList(numSize,i); 393 end 394 %对应的偶数行的nameList就是为空了 395 fileInfoResult(numClass,numVideo).nameList(2*numSize,1)={[]};%要注意这里赋空值的操作,一开始直接是[]赋值过去是不可以的 396 %补上这种特殊情况的picSizePartitionCount 397 fileInfoResult(numClass,numVideo).picSizePartitionCount(2*numSize-1,1)=fileInfoPartition(numClass,numVideo).picSizeCount(numSize,1); 398 fileInfoResult(numClass,numVideo).picSizePartitionCount(2*numSize,1)=0; 399 else 400 for i=1:sumRedundancy 401 fileInfoResult(numClass,numVideo).nameList(2*numSize,i)=nameRedundancyTempList(i); 402 end 403 fileInfoResult(numClass,numVideo).picSizePartitionCount(2*numSize,1)=sumRedundancy;%反正都算了sumRedundancy,顺带把计数字段填上 404 fileInfoResult(numClass,numVideo).picSizePartitionCount(2*numSize-1,1)= ... 405 fileInfoPartition(numClass,numVideo).picSizeCount(numSize)-sumRedundancy;%把计数字段不冗余的文件名补齐 406 %顺带把不冗余的文件名补齐 407 numName=1;%这里重新定义一个numName,和上面的(244行)遍历每个类别对应视频下的对应尺寸的文件的多少重复使用变量,但是互不干扰 408 for i=1:fileInfoPartition(numClass,numVideo).picSizeCount(numSize) 409 for j=1:sumRedundancy 410 if strcmp(fileInfoPartition(numClass,numVideo).nameList(numSize,i),fileInfoResult(numClass,numVideo).nameList(2*numSize,j)) 411 %即为找到了这个文件名是冗余文件,那就没必要进行后面的判断 412 break; 413 elseif j==sumRedundancy 414 %如果在j等于sumRedundancy的时候,还没有找到同名文件,说明这个是独特的文件,那么添加到奇数的nameList中 415 fileInfoResult(numClass,numVideo).nameList(2*numSize-1,numName)=fileInfoPartition(numClass,numVideo).nameList(numSize,i); 416 numName=numName+1; 417 end 418 end 419 end 420 end 421 end 422 end 423 end 424 %把结构体fileInfoPartition按阈值为分割在结构体fileInfoResult,耗时 425 disp(' '); 426 disp(['把结构体fileInfoPartition按阈值',num2str(differentCriterion),'为分割在结构体fileInfoResult']); 427 disp(['共耗时:',num2str(toc)]); 428 429 %终于把需要的信息都按照需求整到了结构体fileInfoResult中 430 431 %在路径pathDestination根据标识符simplifyFlag和redundanceFlag 432 %确定是否新建文件夹simplify和redundance,并在下面创建子文件夹0、1...9 433 %保存简化和冗余的数据 434 %要处理的数据的源地址,里面有子文件夹0、1、2...9 435 % pathSource='C:\Users\Dy\Desktop\sy1\val2'; 436 %保存去冗余后数据的路径 437 %pathDestination='C:\Users\Dy\Desktop\彩色视频真实数据\sjdr'; 438 %是否生成无冗余数据的标志符号,为0,不生成,非0生成 439 %simplifyFlag=1; 440 %是否生成冗余数据的标志符号,为0,不生成,非0生成 441 %redundanceFlag=1; 442 %由于创建了两个标志符,所以最简单的编程方法就是一个标志一个标志编程 443 %开始拷贝去冗余的数据 444 tic; 445 if simplifyFlag 446 pathSimplify=[pathDestination,'\simplify']; 447 mkdir(pathSimplify); 448 %[sumClasses,maxFile]=size(fileInfoRaw); 449 %sumVideo=length(videoList);%统计得到video的总数量 450 for numClass=1:sumClasses%对应的类别 451 mkdir([pathSimplify,'\',num2str(numClass-1),'\']); 452 for numVideo=1:sumVideo%对应的视频序号 453 for numSize=1:fileInfoResult(numClass,numVideo).sumSize%对应的尺寸 454 for numName=1:fileInfoResult(numClass,numVideo).picSizePartitionCount(2*numSize-1) 455 copyfile([pathSource,'\',num2str(numClass-1),'\',fileInfoResult(numClass,numVideo).nameList{2*numSize-1,numName}], ... 456 [pathSimplify,'\',num2str(numClass-1),'\',fileInfoResult(numClass,numVideo).nameList{2*numSize-1,numName}]); 457 end 458 end 459 end 460 end 461 end 462 disp(' '); 463 disp(['拷贝简化后的数据共花费时间:',num2str(toc)]); 464 465 %开始拷贝去冗余的数据 466 tic; 467 if redundanceFlag 468 pathredundance=[pathDestination,'\redundance']; 469 mkdir(pathredundance); 470 %[sumClasses,maxFile]=size(fileInfoRaw); 471 %sumVideo=length(videoList);%统计得到video的总数量 472 for numClass=1:sumClasses%对应的类别 473 mkdir([pathredundance,'\',num2str(numClass-1),'\']); 474 for numVideo=1:sumVideo%对应的视频序号 475 for numSize=1:fileInfoResult(numClass,numVideo).sumSize%对应的尺寸 476 for numName=1:fileInfoResult(numClass,numVideo).picSizePartitionCount(2*numSize) 477 copyfile([pathSource,'\',num2str(numClass-1),'\',fileInfoResult(numClass,numVideo).nameList{2*numSize,numName}], ... 478 [pathredundance,'\',num2str(numClass-1),'\',fileInfoResult(numClass,numVideo).nameList{2*numSize,numName}]); 479 end 480 end 481 end 482 end 483 end 484 disp(' '); 485 disp(['拷贝冗余的数据共花费时间:',num2str(toc)]);