簽名圖片背景處理

目的:公司在申請項目填寫計劃書時,需要提交所有參與人員的電子簽名,項目參與人員將電子簽名提交上來(在白紙上寫上名字並拍照發送過來),我這裏需將發送過來的圖片背景變爲純白(爲了美觀),由於人員衆多,普通的PS速度太慢,故編寫下述代碼,該代碼可對某個文件夾下的所有圖片,進行背景處理,大大加快了工作效率

代碼:

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"

#include <iostream>

using namespace std;
using namespace cv;

//讀取指定目錄下的圖片
void getAllFiles(string path, vector<string> &files, string fileType)
{
    long hFile = 0;
    struct _finddata_t fileInfo;
    string p;

    if ((hFile = _findfirst(p.assign(path).append("\\*" + fileType).c_str(), &fileInfo)) != -1) {
        do {
            files.push_back(p.assign(path).append("\\").append(fileInfo.name));
        } while (_findnext(hFile, &fileInfo) == 0);
    }
}

int otsu(IplImage *image)
{
    assert(NULL != image);

    int width = image->width;
    int height = image->height;
    int x = 0, y = 0;
    int pixelCount[256];
    float pixelPro[256];
    int i, j, pixelSum = width * height, threshold = 0;

    uchar* data = (uchar*)image->imageData;

    //初始化
    for (i = 0; i < 256; i++)
    {
        pixelCount[i] = 0;
        pixelPro[i] = 0;
    }

    //統計灰度級中每個像素在整幅圖像中的個數
    for (i = y; i < height; i++)
    {
        for (j = x; j <width; j++)
        {
            pixelCount[data[i * image->widthStep + j]]++;
        }
    }

    //計算每個像素在整幅圖像中的比例
    for (i = 0; i < 256; i++)
    {
        pixelPro[i] = (float)(pixelCount[i]) / (float)(pixelSum);
    }

    //經典ostu算法,得到前景和背景的分割
    //遍歷灰度級[0,255],計算出方差最大的灰度值,爲最佳閾值
    float w0, w1, u0tmp, u1tmp, u0, u1, u, deltaTmp, deltaMax = 0;
    for (i = 0; i < 256; i++)
    {
        w0 = w1 = u0tmp = u1tmp = u0 = u1 = u = deltaTmp = 0;

        for (j = 0; j < 256; j++)
        {
            if (j <= i) //背景部分
            {
                //以i爲閾值分類,第一類總的概率
                w0 += pixelPro[j];
                u0tmp += j * pixelPro[j];
            }
            else       //前景部分
            {
                //以i爲閾值分類,第二類總的概率
                w1 += pixelPro[j];
                u1tmp += j * pixelPro[j];
            }
        }

        u0 = u0tmp / w0;        //第一類的平均灰度
        u1 = u1tmp / w1;        //第二類的平均灰度
        u = u0tmp + u1tmp;        //整幅圖像的平均灰度
                                  //計算類間方差
        deltaTmp = w0 * (u0 - u)*(u0 - u) + w1 * (u1 - u)*(u1 - u);
        //找出最大類間方差以及對應的閾值
        if (deltaTmp > deltaMax)
        {
            deltaMax = deltaTmp;
            threshold = i;
        }
    }
    //返回最佳閾值;
    return threshold;
}

int num = 0; // 圖片編號

//對讀取的圖片盡心處理

void linshiImg(string path)
{
    num++;
    Mat img = imread(path, 0);
    Mat thresImg;
    IplImage img2 = img;
    int threshold2 = otsu(&img2);

  // 若處理效果不理想,可直接將 threshold2  改爲固定值,如:120、150等進行測試;

    threshold(img, thresImg,threshold2, 255, CV_THRESH_BINARY);
    String path2 = "D:\\11_" + to_string(num) + ".png";  //設置存儲圖片的地址及名稱
    imwrite(path2, thresImg); 
}

int main()
{
    vector<string> temp;

// 指定讀取的目錄及圖片類型
    getAllFiles("D:\\img3", temp, ".jpg");
    //視頻切割
    clock_t start, finish;
    start = clock();
    for (int i = 0; i < temp.size(); i++)
    {
        //    cout << temp[i] << endl;
        linshiImg(temp[i]);
    }
}

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章