签名图片背景处理

目的:公司在申请项目填写计划书时,需要提交所有参与人员的电子签名,项目参与人员将电子签名提交上来(在白纸上写上名字并拍照发送过来),我这里需将发送过来的图片背景变为纯白(为了美观),由于人员众多,普通的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]);
    }
}

猜你喜欢

转载自blog.csdn.net/u012840934/article/details/84061510