【嵌入式】Opencv3.4.1繪製中文點陣
阿新 • • 發佈:2018-12-23
目標:利用opencv在圖片上新增文字
- 利用opencv自帶的putText就可以新增數字和英文
- 我們要求新增中文,達到以下效果
目錄
(一)Windows上繪製中文點陣
環境:VS2017+opencv3.4.1
- 建立空專案、新增原始檔Textimage.cpp、配置opencv環境(配置教程點這兒~)
- 思路:
- 從test.txt資料夾獲取將要錄入的姓名和學號,從txt資料夾獲取將要錄入的姓名和學號(test.txt內容如下圖)
- 從lena.jpg獲取將要顯示的背景圖片作為畫布
- 將中文和學號轉換為中文點陣字型檔中的點陣格式
(圖片為數字點陣asc-48x48的“0”、asci-15x16格式“0”、hzkf16x16格式“0”和漢字點陣格式倒置的“啊”)
- 利用opencv畫圖將漢字畫在畫布上
- 完成,執行結果:
原始碼
#pragma warning(disable:4786)
#pragma warning(disable:4996)
#include <stdio.h>
#include <stdlib.h>
#include <cxcore.h>
#include <highgui.h>
#include <direct.h>//_getcwd直接讀取
//#include <unistd.h>//派上要加上這句
using namespace cv;
class ShowName {
public:
ShowName(char *filename);
ShowName(char *name, char* code);
~ShowName();
void openfile();//開啟字型檔
void get_name_code();//獲取漢字的區碼和位碼
void get_mat (unsigned char qh, unsigned char wh);//獲取通過區碼位碼來確定mat
void draw_name(int num);
void getasi(char incode[]);//獲取數字的ASCII碼
void draw_code(int num);
void file_Runtodraw();
protected:
FILE* CONTERNER;//內容提供者即檔案logo.txt
FILE* HZK24;//24字型檔
FILE* ASI816;//ASCII字型檔
unsigned char mat[72];
unsigned char num_mat[16];
char name_code_box[30];
IplImage* img;//圖片
const int MAPSIZE = 24;//字的size
const int INTERSIZE = 5;//插入間隔
unsigned char name_code[3][2];
private:
char *Name;
char *code;
char *Name_code;
int sum_word;//字型數目
int current_num;
};
//函式名稱: ~ShowName
//函式功能: 釋放空間
ShowName::~ShowName() {
cvReleaseImage(&img);
fclose(HZK24);
fclose(ASI816);
if (CONTERNER != NULL)
fclose(CONTERNER);
img = NULL;
HZK24 = NULL;
ASI816 = NULL;
CONTERNER = NULL;
}
//函式名稱: ShowName
//函式功能: 初始化檔案
ShowName::ShowName(char *filename) {
if ((CONTERNER = fopen(filename, "rb")) == NULL)exit(1);
fseek(CONTERNER, 0, SEEK_SET);
fread(name_code_box, 30, 1, CONTERNER);
char *a = name_code_box;
Name_code = a;
sum_word = strlen(Name_code) - 2;
current_num = 0;
openfile();
}
//函式名稱: ShowName
//函式功能: 初始化
ShowName::ShowName(char *name, char* code) {
this->Name = name;
this->code = code;
this->current_num = 0;
this->sum_word = strlen(Name) / 2 + strlen(this->code);
openfile();
}
//函式名稱: openfile
//函式功能: 開啟字型檔和圖片
void ShowName::openfile() {
char pbuf[100];
_getcwd(pbuf, 100);
strcat(pbuf, "/HZKf2424.hz");
char pbufASC[100];
_getcwd(pbufASC, 100);
strcat(pbufASC, "/Asci0816.zf");
// 讀取圖片
if ((img = cvLoadImage("lena.jpg")) == NULL)exit(1);
// 開啟字型檔案
if ((HZK24 = fopen(pbuf, "rb")) == NULL)exit(1);
//開啟asci8*16檔案
if ((ASI816 = fopen(pbufASC, "rb")) == NULL)exit(1);
}
//函式名稱: get_name_code
//函式功能: 獲取漢字的區碼和位碼
void ShowName::get_name_code() {
for (int i = 0; i < 3; ++i)
for (int j = 0; j < 2; ++j)
name_code[i][j] = Name[i * 2 + j] - 0xa0;
}
//函式名稱: get_mat
//函式功能: 通過漢字的區碼和位碼進行寫到mat中
void ShowName::get_mat(unsigned char qh, unsigned char wh) {
long offset;
offset = (94 * (qh - 1) + (wh - 1)) * 72L;
// 讀取資料存入陣列
fseek(HZK24, offset, SEEK_SET);
fread(mat, 72, 1, HZK24);
}
//函式名稱: draw_name
//函式功能: 通過漢字的區碼和位碼進行寫到mat中
void ShowName::draw_name(int num) {
// 圖片的畫素值
int width, height;
width = img->width;
height = img->height;
// 開始的x y畫素點
int start_x, start_y, size, current_start_x, current_start_y;
size = MAPSIZE;// +INTERSIZE;
start_x = width - sum_word * size;
start_y = height - MAPSIZE - INTERSIZE;
// 開始繪製
CvScalar cs;
for (int i = 0; i < 24; ++i)
for (int j = 0; j < 3; ++j)
for (int k = 0; k < 8; k++)
if (((mat[i * 3 + j] >> (7 - k)) & 0x1) != NULL)
{
// 繪點
current_start_x = start_x + i + size * num;//24*24的是縱向排列的i對應的是x
current_start_y = start_y + j * 8 + k;
cs = cvGet2D(img, current_start_y, current_start_x);
cs.val[0] = 0;
cs.val[1] = 255;//rgb控制的姓名顏色,可更改
cs.val[2] = 255;
cvSet2D(img, current_start_y, current_start_x, cs);
}
}
//函式名稱: getasi
//函式功能: 獲取asci碼
void ShowName::getasi(char incode[]) {
unsigned char qh, wh;
unsigned long offset;
offset = incode[0] * 16L;
fseek(ASI816, offset, SEEK_SET);
fread(num_mat, 16, 1, ASI816);
}
//函式名稱: draw_code
//函式功能: 繪製學號
void ShowName::draw_code(int num) {
int width, height;
width = img->width;
height = img->height;
// 開始的x y畫素點
int start_x, start_y, size, current_start_x, current_start_y;
size = MAPSIZE; //+INTERSIZE;
//int numsize = 8;
start_x = width - sum_word * size;
start_y = height - 16 - INTERSIZE;
// 開始繪製
CvScalar cs;
for (int i = 0; i < 16; ++i)
for (int k = 0; k < 8; k++)
if ((num_mat[i] & (0x80 >> k)) != NULL)
{
current_start_x = k + start_x + size * num;
current_start_y = start_y + i;
cs = cvGet2D(img, current_start_y, current_start_x);//獲取影象相對位置的RGB的值
cs.val[0] = 255;
cs.val[1] = 255;//這裡可以改成你喜歡的顏色,rgb控制學號的顏色
cs.val[2] = 0;
cvSet2D(img, current_start_y, current_start_x, cs);//重新設值
}
}
//函式名稱: file_Runtodraw
//函式功能: 啟動繪製
void ShowName::file_Runtodraw() {
unsigned char mask = 0x80;
char tmpcode[3] = { 0 };
int x = 0;
while (*Name_code != NULL)
{
tmpcode[0] = *Name_code;
tmpcode[1] = *(Name_code + 1);
if (tmpcode[0] & mask) {
unsigned char qh, wh;
qh = tmpcode[0] - 0xaf;
wh = tmpcode[1] - 0xa0;
get_mat(qh, wh);
draw_name(current_num++);
Name_code += 2;
}
else if (tmpcode[0]) {
getasi(Name_code);
draw_code(current_num++);
Name_code++;
}
}
cvShowImage("Textimage", img);
cvWaitKey();
}
int main() {
char *filename = (char*) "test.txt";
ShowName *newname = new ShowName(filename);
newname->file_Runtodraw();
delete newname;
return 0;
}
(二)樹莓派繪製中文點陣
- 用teamviewer將
中文點陣字型檔檔案
和圖片
、之前在windows上建立Textimage.cpp
和test.txt檔案
打包傳到樹莓派上,如圖:
- 雙擊.cpp檔案進入修改程式碼檔案
- 新增目錄:#include <unistd.h>
- 修改2處 _getcwd(pbuf, 100); 把前面_刪掉
- 命令列模式進入當前目錄:
//.cpp目錄
cd /home/pi/test_wy/opencv_test/test4_Add_Chinese_Front
- G++編譯:
g++ Textimage.cpp -o Test `pkg-config --cflags --libs opencv`
- 得到Test可執行檔案
ls
./Test
原始碼
#pragma warning(disable:4786)
#pragma warning(disable:4996)
#include <stdio.h>
#include <stdlib.h>
#include <cxcore.h>
#include <highgui.h>
#include <unistd.h>
using namespace cv;
class ShowName {
public:
ShowName(char *filename);
ShowName(char *name, char* code);
~ShowName();
void openfile();//´ò¿ª×Ö¿â
void get_name_code();//»ñÈ¡ºº×ÖµÄÇøÂëºÍλÂë
void get_mat(unsigned char qh, unsigned char wh);//»ñȡͨ¹ýÇøÂëλÂëÀ´È·¶¨mat
void draw_name(int num);
void getasi(char incode[]);//»ñÈ¡Êý×ÖµÄASCIIÂë
void draw_code(int num);
void file_Runtodraw();
protected:
FILE* CONTERNER;//ÄÚÈÝÌṩÕß¼´Îļþlogo.txt
FILE* HZK24;//24×Ö¿â
FILE* ASI816;//ASCII×Ö¿â
unsigned char mat[72];
unsigned char num_mat[16];
char name_code_box[30];
IplImage* img;//ͼƬ
const int MAPSIZE = 24;//×ÖµÄsize
const int INTERSIZE = 5;//²åÈë¼ä¸ô
unsigned char name_code[3][2];
private:
char *Name;
char *code;
char *Name_code;
int sum_word;//×ÖÌåÊýÄ¿
int current_num;
};
//º¯ÊýÃû³Æ£º ~ShowName
//º¯Êý¹¦ÄÜ£º ÊÍ·Å¿Õ¼ä
ShowName::~ShowName() {
cvReleaseImage(&img);
fclose(HZK24);
fclose(ASI816);
if (CONTERNER != NULL)
fclose(CONTERNER);
img = NULL;
HZK24 = NULL;
ASI816 = NULL;
CONTERNER = NULL;
}
//º¯ÊýÃû³Æ£º ShowName
//º¯Êý¹¦ÄÜ£º ³õʼ»¯Îļþ
ShowName::ShowName(char *filename) {
if ((CONTERNER = fopen(filename, "rb")) == NULL)exit(1);
fseek(CONTERNER, 0, SEEK_SET);
fread(name_code_box, 30, 1, CONTERNER);
char *a = name_code_box;
Name_code = a;
sum_word = strlen(Name_code) - 2;
current_num = 0;
openfile();
}
//º¯ÊýÃû³Æ£º ShowName
//º¯Êý¹¦ÄÜ£º ³õʼ»¯
ShowName::ShowName(char *name, char* code) {
this->Name = name;
this->code = code;
this->current_num = 0;
this->sum_word = strlen(Name) / 2 + strlen(this->code);
openfile();
}
//º¯ÊýÃû³Æ£º openfile
//º¯Êý¹¦ÄÜ£º ´ò¿ª×Ö¿âºÍͼƬ
void ShowName::openfile() {
char pbuf[100];
getcwd(pbuf, 100);
strcat(pbuf, "/HZKf2424.hz");
char pbufASC[100];
getcwd(pbufASC, 100);
strcat(pbufASC, "/Asci0816.zf");
// ¶ÁȡͼƬ
if ((img = cvLoadImage("lena.jpg")) == NULL)exit(1);
// ´ò¿ª×ÖÌåÎļþ
if ((HZK24 = fopen(pbuf, "rb")) == NULL)exit(1);
//´ò¿ªasci8*16Îļþ
if ((ASI816 = fopen(pb