1. 程式人生 > >【嵌入式】Opencv3.4.1繪製中文點陣

【嵌入式】Opencv3.4.1繪製中文點陣

目標:利用opencv在圖片上新增文字

  • 利用opencv自帶的putText就可以新增數字和英文
  • 我們要求新增中文,達到以下效果
    在這裡插入圖片描述

目錄

(一)Windows上繪製中文點陣

環境:VS2017+opencv3.4.1

  1. 建立空專案、新增原始檔Textimage.cpp、配置opencv環境(配置教程點這兒~
    在這裡插入圖片描述
  2. 思路:
  • 從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; }

(二)樹莓派繪製中文點陣

  1. 用teamviewer將中文點陣字型檔檔案圖片、之前在windows上建立Textimage.cpptest.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