1. 程式人生 > >關於印象筆記的掃描寶——簡單的影象背景去除(去底色)演算法小結

關於印象筆記的掃描寶——簡單的影象背景去除(去底色)演算法小結

         前段時間研究了下印象筆記的掃描寶,發現它將手機拍下的照片都能處理成白板背景,而且處理的很乾淨,出於好奇並學習,自己琢磨出了個簡易的去底色演算法,雖然不能跟印象筆記的相比,但是效果也還闊以,供自己學習了,有興趣的朋友歡迎指教。

        文中測試圖分別如下:

圖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;
                    }
                }
                
            }
        }
    }

效果如下:


           不難發現還是有一些瑕疵在的,希望能與大家交流討論。。