关于印象笔记的扫描宝——简单的图像背景去除(去底色)算法小结
2016-03-09 18:11
543 查看
前段时间研究了下印象笔记的扫描宝,发现它将手机拍下的照片都能处理成白板背景,而且处理的很干净,出于好奇并学习,自己琢磨出了个简易的去底色算法,虽然不能跟印象笔记的相比,但是效果也还阔以,供自己学习了,有兴趣的朋友欢迎指教。
文中测试图分别如下:
图1
![](http://img.blog.csdn.net/20160309173536286?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
图2
![](http://img.blog.csdn.net/20160309173554974?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
图3
![](http://img.blog.csdn.net/20160309173506376?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
图4
![](http://img.blog.csdn.net/20160309173608408?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
法一:伽马变换
主要思想:调整色阶,明暗图像求加;
效果如下:
![](http://img.blog.csdn.net/20160309174103241?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
![](http://img.blog.csdn.net/20160309174011178?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
![](http://img.blog.csdn.net/20160309174041085?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
![](http://img.blog.csdn.net/20160309174126194?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
法二:替换背景的像素值;
主要思想,首先遍历图像(遍历可以优化),统计出图像中最多的颜色像素,然后替换成255;
效果如下:
![](http://img.blog.csdn.net/20160309175805670?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
![](http://img.blog.csdn.net/20160309174842128?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
![](http://img.blog.csdn.net/20160309175748141?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
![](http://img.blog.csdn.net/20160309175820513?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
不难发现还是有一些瑕疵在的,希望能与大家交流讨论。。
文中测试图分别如下:
图1
图2
图3
图4
法一:伽马变换
主要思想:调整色阶,明暗图像求加;
void ls::gamma2Add(cv::Mat &src,cv::Mat &dst) { Mat image; resize(src, image, Size(((float)src.cols/(float)src.rows)*krows,krows)); Scan scan; cv::Mat dst1,dst2; scan.gammaCorrection(image, dst1, 0.45); scan.gammaCorrection(image, dst2, 2); dst = dst1 + dst2; }
效果如下:
法二:替换背景的像素值;
主要思想,首先遍历图像(遍历可以优化),统计出图像中最多的颜色像素,然后替换成255;
void changeRGB(Mat &src) { // Mat image; // detailEnhance(src, src); Mat gray; cvtColor(src, gray, CV_BGR2GRAY); MatND hist = getHistogram(gray); double maxVal = 0,minVal = 0; //获取最大值和最小值 int hpt = static_cast<int>(0.9 * histSize[0]); minMaxLoc(hist, &minVal, &maxVal,0,0); cout<<minVal<<","<<maxVal<<endl; vector<int> kChange; // int th = me / maxVal; // int nonzero = countNonZero(gray); // double ratio = nonzero / (double)(gray.cols * gray.rows); // cout<<ratio<<endl; for (int i = 0; i < histSize[0]; i ++) { float binVal = hist.at<float>(i); //cout<<binVal<<endl; int intensity = static_cast<int>(binVal*hpt/maxVal); if (abs(intensity - 255) < 60) { intensity = 255; hist.at<float>(i) = intensity * maxVal/hpt; } // if (abs(intensity - 0) > 30) { // intensity = 0; // hist.at<float>(i) = intensity * maxVal/hpt; // } // } minMaxLoc(hist,&minVal, &maxVal,0,0); cout<<minVal<<","<<maxVal<<endl; for (int num = 0; num < histSize[0]; num ++) { if (hist.at<float>(num) >= 0.5*maxVal)//( hist.at<float>(i) >= ratio*maxVal && hist.at<float>(i) <= 1.0*maxVal)//3.63 { kChange.push_back(num); } } int nl = src.rows; int nc = src.cols; // if (src.isContinuous()) { // nc = nc * nl; // nl = 1; // } for (int j = 0; j < nl; j ++) { // uchar *data = src.ptr<uchar>(j); for (int l = 0; l < nc; l ++) { int b = 0.11 * src.at<Vec3b>(j, l)[0]; int g = 0.59 * src.at<Vec3b>(j, l)[1]; int r = 0.30 * src.at<Vec3b>(j, l)[2]; int greyVal = b + g + r; for (int ii = 0; ii < kChange.size(); ii ++) { if (abs(greyVal - kChange[ii]) <= 18)// // if (greyVal == kChange[ii]) { src.at<Vec3b>(j, l)[0] = 255; src.at<Vec3b>(j, l)[1] = 255; src.at<Vec3b>(j, l)[2] = 255; } } } } }
效果如下:
不难发现还是有一些瑕疵在的,希望能与大家交流讨论。。
相关文章推荐
- java学习之自定义异常
- HBase纪要
- 一次sql排序的问题。
- jquery checkbox checked
- [LeetCode][JavaScript]Find Minimum in Rotated Sorted Array II
- 深入解析设计模式中的适配器模式在C++中的运用
- java中类序列化与反序列化的实现
- js注意事项
- Codeforces 651E:Table Compression
- 使用外网控制你的STM32单片机
- linux自己主动重新启动tomcat脚本
- C++ MPICH
- <原创> 通过PEB获得进程路径 (附完整工程)
- 2016蓝桥杯假期任务之《核桃的数量 》
- 在eclipse中配置opencv开发环境
- ActiveMQ学习心得之ActiveMQ四种存储器分析
- ScaleType简单属性介绍
- 我的Node.js处女作
- FastReport.Net 常用功能总汇
- 自定义UITableViewCell(registerNib: 与 registerClass: 的区别)