
今天聽說很多同志們寫畢業論文重復率過高的問題,大牛說用圖片代替字就行了,我就想用OpenCV實現一下看看能不能搞,果不其然還是可以的!!!主要的難點在於普通格式的圖片背景不透明,需要使用背景透明的png格式圖片就行。
主要思想和步驟:
1.首先配置好FreeType與OpenCV,添加編譯好的lib,與include目錄和CvxText.h和CvxText.cpp就行了,參考[1]
2.說一下思路,主要就是OpenCV版本的問題造成有的函數用的IplImage,而函數
//設置原圖像文字
text.putText(ImageSrc, msg, cvPoint(1, size_zi), color);
只能接受IplImage格式的參數,所以保存成png,就比較麻煩了。
png格式的圖片是4個通道,按照BGRA來放置,alaph就是透明通道。我們的思路就是按照原來直接給圖片上疊加文字的辦法,新建與文字大小相同的圖片,然后二值化,按照二值模版生成新的png文字圖片,有字的地方添上顏色,沒字的地方設置為透明。
當然二值化算法網上搜了一個自適應閥值的算法效果非常好:參考[3]
3.生成了透明的文字圖片,粘貼到論文里面,估計查詢重復的系統再牛逼也是無能為力了。后序有空做一些程序界面跟字符分割的東西,可以直接賣錢了。
當然,字體跟大小,上下邊距都是可以設置的,后序再往程序里面寫。
實現效果:



主要代碼:
// AddChinese.cpp : 定義控制台應用程序的入口點。
//
#include "stdafx.h"
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include "CvxText.h"
#pragma comment(lib,"freetype255d.lib")
#pragma comment(lib,"opencv_core2410d.lib")
#pragma comment(lib,"opencv_highgui2410d.lib")
#pragma comment(lib,"opencv_imgproc2410d.lib")
using namespace std;
using namespace cv;
#define ROW_BLOCK 2
#define COLUMN_Block 2
// writePng.cpp : 定義控制台應用程序的入口點。
//
int run_test_png(Mat &mat,string image_name)
{
/*采用自己設置的參數來保存圖片*/
//Mat mat(480, 640, CV_8UC4);
//createAlphaMat(mat);
vector<int> compression_params;
compression_params.push_back(CV_IMWRITE_PNG_COMPRESSION);
compression_params.push_back(9); //png格式下,默認的參數為3.
try
{
imwrite(image_name, mat, compression_params);
}
catch (runtime_error& ex)
{
fprintf(stderr, "Exception converting image to PNG format: %s\n", ex.what());
return 1;
}
fprintf(stdout, "Saved PNG file with alpha data.\n");
waitKey(0);
return 0;
}
int coloured(Mat &template_src, Mat &mat_png, CvScalar color)
{
for (int i = 0; i < template_src.rows; ++i)
{
for (int j = 0; j < template_src.cols; ++j)
{
Vec4b& bgra = mat_png.at<Vec4b>(i, j);
//int temp = template_src.at<uchar>(i,j);
if (template_src.at<uchar>(i,j)== 0)
{
bgra[0] = color.val[0]; //b通道
bgra[1] = color.val[1]; //g通道
bgra[2] = color.val[2]; //r通道
bgra[3] = 255;//alpha通道全部設置為透明完全透明為0,否則為255
}
else
{
bgra[3] = 0;//alpha通道全部設置為透明完全透明為0,否則為255
}
}
}
return 0;
}
void ImageBinarization(IplImage *src)
{ /*對灰度圖像二值化,自適應門限threshold*/
int i,j,width,height,step,chanel,threshold;
/*size是圖像尺寸,svg是灰度直方圖均值,va是方差*/
float size,avg,va,maxVa,p,a,s;
unsigned char *dataSrc;
float histogram[256];
width = src->width;
height = src->height;
dataSrc = (unsigned char *)src->imageData;
step = src->widthStep/sizeof(char);
chanel = src->nChannels;
/*計算直方圖並歸一化histogram*/
for(i=0; i<256; i++)
histogram[i] = 0;
for(i=0; i<height; i++)
for(j=0; j<width*chanel; j++)
{
histogram[dataSrc[i*step+j]-'0'+48]++;
}
size = width * height;
for(i=0; i<256; i++)
histogram[i] /=size;
/*計算灰度直方圖中值和方差*/
avg = 0;
for(i=0; i<256; i++)
avg += i*histogram[i];
va = 0;
for(i=0; i<256; i++)
va += fabs(i*i*histogram[i]-avg*avg);
/*利用加權最大方差求門限*/
threshold = 20;
maxVa = 0;
p = a = s = 0;
for(i=0; i<256; i++)
{
p += histogram[i];
a += i*histogram[i];
s = (avg*p-a)*(avg*p-a)/p/(1-p);
if(s > maxVa)
{
threshold = i;
maxVa = s;
}
}
/*二值化*/
for(i=0; i<height; i++)
for(j=0; j<width*chanel; j++)
{
if(dataSrc[i*step+j] > threshold)
dataSrc[i*step+j] = 255;
else
dataSrc[i*step+j] = 0;
}
}
Mat binaryzation(Mat &src)
{
Mat des_gray(src.size(),CV_8UC1);
cvtColor(src,des_gray,CV_BGR2GRAY);
//Mat bin_mat();
IplImage temp(des_gray);
ImageBinarization(&temp);
//threshold(des_gray,des_gray,150,255,THRESH_BINARY);
imshow("二值圖像",des_gray);
return des_gray;
}
int generate_chinese(const int size_zi, const char *msg ,int number,CvScalar color)
{
//int size_zi = 50;//字體大小
CvSize czSize; //目標圖像尺寸
float p = 0.5;
CvScalar fsize;
//讀取TTF字體文件
CvxText text("simhei.ttf");
//設置字體屬性 字體大小/空白比例/間隔比例/旋轉角度
fsize = cvScalar(size_zi, 1, 0.1, 0);
text.setFont(NULL, &fsize, NULL, &p);
czSize.width = size_zi*number;
czSize.height = size_zi;
//加載原圖像
IplImage* ImageSrc = cvCreateImage(czSize,IPL_DEPTH_8U,3);//cvLoadImage(Imagename, CV_LOAD_IMAGE_UNCHANGED);
//Mat image(ImageSrc);
//createAlphaMat(image);
//ImageSrc = ℑ
//IplImage temp(image);
//ImageSrc = &temp;
//設置原圖像文字
text.putText(ImageSrc, msg, cvPoint(1, size_zi), color);
//顯示原圖像
cvShowImage("原圖", ImageSrc);
string hanzi = msg;
hanzi = hanzi + ".png";
Mat chinese(ImageSrc,true);
Mat gray = binaryzation(chinese);
imwrite("chinese_gray.jpg",gray);
Mat mat_png(chinese.size(),CV_8UC4);
coloured(gray,mat_png,color);
run_test_png(mat_png,hanzi);
//
////cvSaveImage("hanzi.jpg",reDstImage);
//run_test_png(chinese,hanzi);
//等待按鍵事件
cvWaitKey();
return 0;
}
int main()
{
CvScalar color = CV_RGB(0,0,0);
int size = 200;
const char* msg = "你好a";//暫時一行字不要太長
int number = 3;//字符個數
generate_chinese(size,msg,number,color);
return 0;
}
完整工程下載:
http://download.csdn.net/detail/wangyaninglm/8486521
參考文獻:
http://blog.csdn.net/fengbingchun/article/details/8029337
