关于图像处理方面的收获:
五月中旬的时候接了个细胞检测的活,要求识别白细胞、红细胞、脂肪球、霉菌几种
细胞,大致看了客户发给我显微镜上的图片,发现能做,于是就接了下来,客户告诉
我最终的程序要是C++的编译成DLL给他们的应用程序调用才可以,本人因为一直做
Java,做C++还是12年前毕业设计的时候做了图像相关的东西。从那之后,做项目偶
尔也会搞点C++但是基本上就一直停留在Hello World的水平上。我的想法是先把算法
用Java实现,然后我找人合作帮忙把算法从Java翻译成C++,经过大概一个月左右的
时间Java版本的算法已经实现,并且用客户给我的那些测试图片数据,发现除了白细
胞识别率有点低,其它的识别都还不错,基本都在70%左右,而且阴性的检测准确率
高达96%,已经满足实际需要。其实做这个识别算法我是基于模板匹配方法,但是唯
一不同的时候我是先找到ROI区域,然后只对ROI区域去做模板匹配,这样速度就非常
快,基本满足了客户要求。在做这个项目的过程中,自己对一些基础的问题又有了近
一步的认知,对SMOOTH、先图像梯度在灰度还是先灰度在梯度的区别都有了新的认
知,发现顺序不同差别还是很大的,对图像二值化、二值图像的填充、腐蚀与膨胀、
开闭操作、边缘提取等都更加的熟悉了。同时对霍夫直线检测、二值图像的连通区域
查找等算法也有近一步的认识,在特征提取方面自己先后尝试了LBP、HOG、几何距
灰度共生矩阵等又温习和进一步理解应用。通过综合运用这些知识,基于提取到的模
板数据、实现了对细胞的快速分类与识别。
关于编程方面的收获:
我在学习图像处理之初,就下定决心不去依赖任何库,这样做有好处也有坏处,好处
就是逼着自己去实现一些常见的图像处理方法,坏处就工作效率比较低,特别是开始
阶段,我在用Java做这些算法的时候也特别注意借鉴ImageJ中的代码,能直接拿过来
用的,我基本都直接拿过来了,HOG是我自己用Java写的,因为ImageJ中我没发现
这个就导致我的Java算法在翻译到C++的时候有很多选择,可以用openCV等开源库
可以那些API我也没仔细看,心想找个人帮我翻译成C++的就好了,不需要任何库
毕竟我的Java版算法也是我自己实现的,不依赖任何库,我估计的时间是一周左右
我很幸运的找到一个很好的C++哥们,他也是CSDN的一个熟人,花了两周晚上的时
间我们把Java的算法转成C++的了,然后编译测试通过,改了几个小问题就发现运行
结果跟Java没有差别,这个让我很高兴,觉得帮我翻译C++的哥们太给力了,希望我
们一直合作下去。
当然这个过程中我们也踩了不少坑,其中最大的一个就是我Java做的算法很多变
量都没有初始化为0,到了C++上面就悲剧了,还有一些数组也没有初始化就直接进行
像素或者统计操作,结果也很悲剧,都是很大的坑。费了我们不少精力。其中更有一
个很恶搞的问题,我定义的数字是字节类型的,结果里面的数据是INT的,长度就会溢
出,结果就很悲剧。我也学会一些简单的C++知识,学会用vs2015搞东西,学会了用
CxImage这个库来读图像文件和像素数据。复活了我一些VC++的知识。我记得我上次
用VC++的时候还是6.0,我这个跨度比较大。项目总结的时候那哥们还给我提几点建议
这样方面他把代码转到C++。一个很认真的哥们,他的建议:
对以后咱们合作中的Java代码提两点建议:
1.定义变量、数组时必须初始化。
2.逻辑层和视图层分离,算法中只传像素数组,
不要有BufferedImage对象及图像读定相关的操作,
这些都放到视图层。对图像的处理,其实就是对像素的处理。
那么处理函数的定义其实只需要传入一个待处理的像素数组,
返回一个处理后的结果像素数组。Java定义可以为:
public abstract int [] process( int[] pixs,int width, int height);
对应的c++定义为
virtual int process (EUINT32 * pSrcPix ,int nSrcW , int nSrcH , EUINT32 *& pDest , int & nDestW , int &nDestH ) = 0;
关于我们:
如果能在一起做事情,一定要相互信任,特别是经济上一定要相互讲清楚,只有这样
团队才会相互信任,才有可能一起做更多的事情。要让客户看到自己的努力,认可自
己的劳动,成功就不会太远了。现在我做Java,主攻图像处理的各种算法,他主攻
C++,我们相互是对方的老师和良师。就在这个项目结束的时候我们又接一个新的图
像处理的活,希望会一起走的更远。