目的:公司在申請項目填寫計劃書時,需要提交所有參與人員的電子簽名,項目參與人員將電子簽名提交上來(在白紙上寫上名字並拍照發送過來),我這裏需將發送過來的圖片背景變爲純白(爲了美觀),由於人員衆多,普通的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]);
}
}