主頁 > 區塊鏈 > 【OpenCV3.4.7+VS2017】基于顏色閾值分割以及對于藍色車的邊緣檢測(川字分割)(模板匹配)的車牌識別專案(分版塊代碼可直接運行)

【OpenCV3.4.7+VS2017】基于顏色閾值分割以及對于藍色車的邊緣檢測(川字分割)(模板匹配)的車牌識別專案(分版塊代碼可直接運行)

2020-09-18 10:32:48 區塊鏈

一、車牌的識別和校正

本文采用一工程多專案模式,以代碼呈現,因還未接觸MFC,所以敬請見諒,之后會繼續學習,不斷完善代碼,

車牌識別借鑒于CSDN博主吾理小子的博客,表達由衷的感謝!https://blog.csdn.net/qq_39960119/article/details/83930112
對其中的一些引數和定義做了一些修改,增加了對傾斜圖片的修正,不過鄙人對于傾斜角度引數的理解依舊不到位,因此對于角度的處理還是不太理解,屬實慚愧,

#include <iostream>
#include <opencv2\opencv.hpp>

using namespace std;
using namespace cv;

int main()

{

	Mat OriginalImg;
	
	OriginalImg = imread("TestPhoto.jpg", IMREAD_COLOR);//讀取原始彩色影像
	
	if (OriginalImg.empty())  //判斷影像對否讀取成功

	{

		cout << "錯誤!讀取影像失敗\n";

		return -1;

	}

	//	imshow("原圖", OriginalImg); //顯示原始影像

	cout << "Width:" << OriginalImg.rows << "\tHeight:" << OriginalImg.cols << endl;//列印長寬



	Mat ResizeImg;

	//if (OriginalImg.cols > 640)

	resize(OriginalImg, ResizeImg, Size(640, 640 * OriginalImg.rows / OriginalImg.cols));

	imshow("尺寸變換圖", ResizeImg);



	unsigned char pixelB, pixelG, pixelR;  //記錄各通道值

	unsigned char DifMax = 65;             //基于顏色區分的閾值設定

	unsigned char B = 200, G = 80, R = 50; //各通道的閾值設定,針對與藍色車牌

	Mat BinRGBImg = ResizeImg.clone();  //二值化之后的影像

	int i = 0, j = 0;

	for (i = 0; i < ResizeImg.rows; i++)   //通過顏色分量將圖片進行二值化處理

	{

		for (j = 0; j < ResizeImg.cols; j++)

		{

			pixelB = ResizeImg.at<Vec3b>(i, j)[0]; //獲取圖片各個通道的值

			pixelG = ResizeImg.at<Vec3b>(i, j)[1];

			pixelR = ResizeImg.at<Vec3b>(i, j)[2];



			if (abs(pixelB - B) < DifMax && abs(pixelG - G) < DifMax && abs(pixelR - R) < DifMax)

			{                                           //將各個通道的值和各個通道閾值進行比較

				BinRGBImg.at<Vec3b>(i, j)[0] = 255;     //符合顏色閾值范圍內的設定成白色

				BinRGBImg.at<Vec3b>(i, j)[1] = 255;

				BinRGBImg.at<Vec3b>(i, j)[2] = 255;

			}

			else

			{

				BinRGBImg.at<Vec3b>(i, j)[0] = 0;        //不符合顏色閾值范圍內的設定為黑色

				BinRGBImg.at<Vec3b>(i, j)[1] = 0;

				BinRGBImg.at<Vec3b>(i, j)[2] = 0;

			}

		}

	}

	imshow("基于顏色資訊二值化", BinRGBImg);        //顯示二值化處理之后的影像



	Mat BinOriImg;     //形態學處理結果影像

	Mat element = getStructuringElement(MORPH_RECT, Size(3, 3)); //設定形態學處理窗的大小
    dilate(BinRGBImg, BinOriImg, element,Point(-1, -1), 5);     //進行多次膨脹操作
	erode(BinOriImg, BinOriImg, element,Point(-1,-1),5);      //進行多次腐蝕操作
	imshow("形態學處理后", BinOriImg);        //顯示形態學處理之后的影像
	
	//--------------------------------------------------------------------------


	double length, area, rectArea;     //定義輪廓周長、面積、外界矩形面積

	double rectDegree = 0.0;           //矩形度=外界矩形面積/輪廓面積,比值越大說明效果越好

	double long2Short = 0.0;           //體態比=長邊/短邊

	CvRect rect;           //外界矩形:結構體包含x,y坐標,width和height

	CvBox2D box, boxTemp;  //外接矩形

	CvPoint2D32f pt[4];    //矩形定點變數

	double axisLong = 0.0, axisShort = 0.0;        //矩形的長邊和短邊

	/*double axisLongTemp = 0.0, axisShortTemp = 0.0;*///矩形的長邊和短邊

	double LengthTemp;     //中間變數

	float  angle = 0;      //記錄車牌的傾斜角度

	bool   TestPlantFlag = 0;  //車牌檢測成功標志位

	cvtColor(BinOriImg, BinOriImg, CV_BGR2GRAY);   //將形態學處理之后的影像轉化為灰度影像

	threshold(BinOriImg, BinOriImg, 100, 255, THRESH_BINARY); //灰度影像二值化,//OTSU演算法(雙峰圖效果明顯)

	CvMemStorage *storage = cvCreateMemStorage(0);//跟堆疊類似

	CvSeq * seq = 0;     //創建一個序列,CvSeq本身就是一個可以增長的序列,不是固定的序列

	CvSeq * tempSeq = cvCreateSeq(CV_SEQ_ELTYPE_POINT, sizeof(CvSeq), sizeof(CvPoint), storage);//以點坐標形式,序列頭大小,儲存元素大小,儲存在之前的容器里

	int cnt = cvFindContours(&(IplImage(BinOriImg)), storage, &seq, sizeof(CvContour), CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);

	//第一個引數是IplImage指標型別,將MAT強制轉換為IplImage指標型別

	//回傳輪廓的數目 

	//獲取二值影像中輪廓的個數

	cout << "number of contours   " << cnt << endl;  //列印輪廓個數

	for (tempSeq = seq; tempSeq != NULL; tempSeq = tempSeq->h_next)

	{

		length = cvArcLength(tempSeq);       //獲取輪廓周長

		area = cvContourArea(tempSeq);       //獲取輪廓面積

		if (area > 800 && area < 50000)     //矩形區域面積大小判斷

		{

			rect = cvBoundingRect(tempSeq, 1);//計算矩形邊界

			boxTemp = cvMinAreaRect2(tempSeq, 0);  //獲取輪廓的矩形

			cvBoxPoints(boxTemp, pt);              //獲取矩形四個頂點坐標

			angle = boxTemp.angle;                 //得到車牌傾斜角度



			axisLong = sqrt(pow(pt[1].x - pt[0].x, 2) + pow(pt[1].y - pt[0].y, 2));  //計算長軸(勾股定理)

			axisShort = sqrt(pow(pt[2].x - pt[1].x, 2) + pow(pt[2].y - pt[1].y, 2)); //計算短軸(勾股定理)
			Point2d points;
			vector<Point>dots;
			for (int i = 0; i < 4; i++)
			{
				points.x = pt[i].x;
				points.y = pt[i].y;
				dots.push_back(points);
			}
			RotatedRect rect = minAreaRect(dots);

			if (axisShort > axisLong)   //短軸大于長軸,交換資料

			{

				LengthTemp = axisLong;

				axisLong = axisShort;

				axisShort = LengthTemp;

			}

			else

				angle += 90;


			rectArea = axisLong * axisShort;  //計算矩形的面積

			rectDegree = area / rectArea;     //計算矩形度(比值越接近1說明越接近矩形)



			long2Short = axisLong / axisShort; //計算長寬比

			if (long2Short > 2.2 && long2Short < 3.8 && rectDegree > 0.63 && rectDegree < 1.37 && rectArea > 2000 && rectArea < 50000)

			{

				Mat GuiRGBImg = ResizeImg.clone();

				TestPlantFlag = true;             //檢測車牌區域成功

				for (int i = 0; i < 4; ++i)       //劃線框出車牌區域

					cvLine(&(IplImage(GuiRGBImg)), cvPointFrom32f(pt[i]), cvPointFrom32f(pt[((i + 1) % 4) ? (i + 1) : 0]), CV_RGB(255, 0, 0));//實作閉口畫線

				imshow("提取車牌結果圖", GuiRGBImg);    //顯示最終結果圖

			

				if (angle != 0)
				{
					Point2f center(pt->x + (axisLong / 2), pt->y - (axisLong / 2));
					Mat warp = getRotationMatrix2D(center, angle, 1.0);
					warpAffine(OriginalImg, OriginalImg, warp, Size(640, 640 * OriginalImg.rows / OriginalImg.cols));//不設定會出現記憶體問題
					resize(OriginalImg, OriginalImg, Size(640, 640 * OriginalImg.rows / OriginalImg.cols));
					imshow("旋轉后的原圖", OriginalImg);
					imwrite("affineimg.jpg", OriginalImg);
				}
				else
				{
					Mat img_ROI = GuiRGBImg(Rect(pt->x+2, pt->y - axisShort+2, axisLong, axisShort));//提取感興趣區域這里+2是為了修正紅色矩形邊框
					imshow("車牌", img_ROI);
					resize(img_ROI, img_ROI, Size(354, 118));
					imshow("車牌2", img_ROI);
					imwrite("affineimg.jpg", img_ROI);
				}
				cout << "傾斜角度:" << angle << endl;

			}

		}

	}
	waitKey();

	return 0;



}

代碼運行效果圖如下:

運行結果

二、獲取車牌

此處是對修正后的原圖進行的處理,提取為354×118像素的車牌校正后的圖片
識別與提取的代碼上面寫過了,拿過來用就行,

Mat img_ROI = GuiRGBImg(Rect(pt->x - axisLongTemp+2, pt->y - axisShortTemp+2, axisLongTemp-5, axisShortTemp-5));//提取感興趣區域

				imshow("車牌", img_ROI);
				resize(img_ROI, img_ROI, Size(354, 118));
				imshow("車牌2", img_ROI);
				imwrite("img_ROI.jpg", img_ROI);

運行結果如下:運行結果

二·1 邊緣檢測法

借鑒于CSDN博主Nine-days的部分代碼,并做了一些完善和普適兼容,表達由衷的感謝!https://blog.csdn.net/u011808673/article/details/78510692

int main()
{
	Mat OriginalImg;

	OriginalImg = imread("blurcar.jpg", IMREAD_COLOR);//讀取原始彩色影像

	if (OriginalImg.empty())  //判斷影像對否讀取成功

	{

		cout << "錯誤!讀取影像失敗\n";

		return -1;

	}
	cout << "Width:" << OriginalImg.rows << "\tHeight:" << OriginalImg.cols << endl;//列印長寬



	Mat ResizeImg;
	
	resize(OriginalImg, ResizeImg, Size(640, 640 * OriginalImg.rows / OriginalImg.cols));

	imshow("尺寸變換圖", ResizeImg);
	Mat gray_img;
	cvtColor(ResizeImg, gray_img, CV_RGB2GRAY);
	Mat blur_img;
	blur(gray_img, blur_img, Size(3, 3));
	Mat candy_img;
	Canny(blur_img, candy_img, 300, 100, 3);
	imshow("test", candy_img);

	//形態學處理

    //圖片膨脹處理

	Mat dilate_image, erode_image, BinOriImg;

	//自定義 核進行 x 方向的膨脹腐蝕

	Mat elementX = getStructuringElement(MORPH_RECT, Size(22, 1));

	Mat elementY = getStructuringElement(MORPH_RECT, Size(1, 20));

	Point point(-1, -1);

	dilate(candy_img, dilate_image, elementX, point, 2);

	erode(dilate_image, erode_image, elementX, point, 4);

	dilate(erode_image, dilate_image, elementX, point, 2);



	//自定義 核進行 Y 方向的膨脹腐蝕

	erode(dilate_image, erode_image, elementY, point, 1);

	dilate(erode_image, BinOriImg, elementY, point, 2);

	imwrite("dilate_image.jpg", BinOriImg);

	//噪聲處理

    //平滑處理 中值濾波

	Mat blur_image;

	medianBlur(BinOriImg, blur_image, 15);

	medianBlur(blur_image, blur_image, 15);

	imshow("test2", blur_image);

接下來就是對處理過的影像進行車牌提取,代碼上面寫過了,拿來用就行,運行結果如下圖:運行結果

三、字符分割

此字符分割解決了垂直投影切割“川”字和其他易于被分割錯誤的漢字的問題,簡化了對于車牌中的點被分割的問題,
借鑒于博主lxx_123456的文章,表達由衷的感謝!https://blog.csdn.net/lxx_123456/article/details/79078570

#define _CRT_SECURE_NO_WARNINGS
#define cols_value 0    //cols:2   row:1對于edge搜索
#define row_value 0      //對于川來說不需要去邊框
#include <opencv2/opencv.hpp>
#include <math.h>
#include<vector>
#include<cv.h>
using namespace cv;
using namespace std;

vector<Mat> verticalProjectionMat(Mat Image)//封裝垂直投影  
{
	int perPixelValue;//每個像素的值  
	int width = Image.cols;
	int height = Image.rows;
	printf("圖片的寬%d圖片的高%d", width, height);
	int* projectValArry = new int[width];//創建用于儲存每列白色像素個數的陣列  
	memset(projectValArry, 0, width * 4);//初始化陣列  
	for (int col = 0; col < width; col++)//列  
	{
		int cols_convert_num = 0;
		for (int i = 0; i < height - 1; i++)
		{
			if (Image.at<uchar>(i, col) != Image.at<uchar>(i + 1, col))
				cols_convert_num++;
		}
		if (cols_convert_num < cols_value)
		{
			continue;
		}
		for (int row = 0; row < height; row++)//行  
		{
			int row_convert_num = 0;
			for (int j = 0; j < width - 1; j++)
			{
				if (Image.at<uchar>(row,j) != Image.at<uchar>(row,j+1))
					row_convert_num++;
			}
			if (row_convert_num < row_value)
			{
				continue;
			}
			perPixelValue = Image.at<uchar>(row, col);//每個像素的值
			//if (perPixelValue == 0)//如果是白底黑字  
			if (perPixelValue == 255)//如果是黑底白字
			{
				projectValArry[col]++;//列上的疊加
			}
		}
	}
	Mat verticalProjectionMat(height, width, CV_8U, Scalar(255));//垂直投影的畫布  
	for (int i = 0; i < height; i++)
	{
		for (int j = 0; j < width; j++)
		{
			perPixelValue = 255;  //背景設定為白色  
			verticalProjectionMat.at<uchar>(i, j) = perPixelValue;//遍歷設定背景顏色
		}
	}
	for (int i = 0; i < width; i++)//垂直投影直方圖  
	{
		for (int j = 0; j < projectValArry[i]; j++)
		{
			perPixelValue = 0;  //直方圖設定為黑色    
			verticalProjectionMat.at<uchar>(height - 1 - j, i) = perPixelValue;
		}
	}

	imshow("垂直投影", verticalProjectionMat);//以上是如何讓這個畫布形成的呢
	Rect rect(0, 0, 120, 40);
	Mat image_cut = Mat(verticalProjectionMat, rect);
	Mat image_copy = image_cut.clone();
	//imshow("切割圖片", image_copy);

	vector<Mat> roiList;//用于儲存分割出來的每個字符  
	int startIndex = 0;//記錄進入字符區的索引  
	int endIndex = 0;//記錄進入空白區域的索引  
	bool inBlock = false;//是否遍歷到了字符區內  
	for (int i = 0; i < Image.cols; i++)//cols=width  
	{
		if (!inBlock && projectValArry[i] != 0)//進入字符區  
		{
			inBlock = true;
			startIndex = i;
		}
		else if (projectValArry[i] ==0 && inBlock)//進入空白區  
		{
			
			while (i < Image.cols / 7)//分割漢字
			{
				i++;
			}
			
			endIndex = i;
			inBlock = false;			
			Mat roiImg = Image(Range(0, Image.rows), Range(startIndex, endIndex + 1));
			roiList.push_back(roiImg);
		}
	}
	delete[] projectValArry;
	return roiList;
}
int main()
{
	Point point(-1, -1);

	//Mat Image = imread("E:\\LicenseRecognition\\EdgeSearch\\EdgeSearch\\img_ROI.jpg");
    Mat Image = imread("E:\\LicenseRecognition\\EdgeSearch\\GetPointedLabel\\img_ROI.jpg");//可用不同的路徑
	Mat Image1;
	cvtColor(Image, Image1, CV_BGR2GRAY);
	imshow("灰度化", Image1);
	Mat Image2;
	threshold(Image1, Image2, 158, 255, CV_THRESH_BINARY);//二值化//100,255 Edge//157,255顏色分割 162edge分割
	imshow("二值化", Image2);
	Mat Image3;
	Mat element = getStructuringElement(MORPH_RECT, Size(1,1));
	morphologyEx(Image2, Image3, MORPH_OPEN, element,point,4);//開運算	
	imshow("開運算", Image3);
	int size = 0;
	char szName[30] = { 0 };
	vector<Mat> b = verticalProjectionMat(Image3);
	for (int j = 0; j < b.size(); j++)
	{
		if (j == 2)//去除車牌中的點
		{
			continue;
		}		
		sprintf(szName, "vertical_%d.jpg", j);
		resize(b[j], b[j],Size(20, 40));//不可調整順序,不然質量差
		imshow(szName, b[j]);
		imwrite(szName, b[j]);

	}
	waitKey(0);
}

分割效果:分割效果

四、模板匹配以及識別

借鑒于某車牌識別系統開源原始碼中模板匹配及識別一小部分,
缺點1:8與B、5與6的識別不夠準確(因為是像素相減),幸好鄙人多測驗了幾張圖,發現8與B、5與6的判斷標準恰巧是相反的,算作投機取巧,此為學習研究人士的大忌,若無奈之才疏學淺,實不可取,
缺點2:識別的漢字有限,代碼后加了其他省份的車牌漢字可用作代碼識別修改
如有大佬有解決缺點完善代碼之法可以積極評論指正,在下感激不盡!

//此為head.h頭檔案
#pragma once
#include "cv.h"
#include "highgui.h"

struct pattern
{

	double feature[33]; //樣本的特征向量
	int number;        //待識別字符在樣本庫中的序列號

};

//定義特征提取函式
void GetFeature(IplImage *src, pattern &pat);
#define _CRT_SECURE_NO_WARNINGS
#include "head.h"
#include<opencv2/opencv.hpp>
#include<cstring>
#include<highgui/highgui.hpp>
using namespace cv;
using namespace std;
void GetFeature(IplImage* src, pattern &pat)
{
	CvScalar s;
	int i, j;
	for (i = 0; i < 33; i++)
		pat.feature[i] = 0.0;
	//影像大小是20*40大小的,分成25塊

	//********第一行***********	
	//第一塊
	for (j = 0; j < 8; j++)
	{
		for (i = 0; i < 4; i++)
		{
			s = cvGet2D(src, j, i);
			if (s.val[0] == 255)
				pat.feature[0] += 1.0;
		}
	}

	//第二塊
	for (j = 0; j < 8; j++)
	{
		for (i = 4; i < 8; i++)
		{
			s = cvGet2D(src, j, i);
			if (s.val[0] == 255)
				pat.feature[1] += 1.0;
			
			
		}
	}
	//第三塊
	for (j = 0; j < 8; j++)
	{
		for (i = 8; i < 12; i++)
		{
			s = cvGet2D(src, j, i);
			if (s.val[0] == 255)
				pat.feature[2] += 1.0;
		}
	}
	//第四塊
	for (j = 0; j < 8; j++)
	{
		for (i = 12; i < 16; i++)
		{
			s = cvGet2D(src, j, i);
			if (s.val[0] == 255)
				pat.feature[3] += 1.0;
		}
	}
	//第五塊
	for (j = 0; j < 8; j++)
	{
		for (i = 16; i < 20; i++)
		{
			s = cvGet2D(src, j, i);
			if (s.val[0] == 255)
				pat.feature[4] += 1.0;
		}
	}
	//********第二行***********	
	//第六塊
	for (j = 8; j < 16; j++)
	{
		for (i = 0; i < 4; i++)
		{
			s = cvGet2D(src, j, i);
			if (s.val[0] == 255)
				pat.feature[5] += 1.0;
		}
	}
	//第七塊
	for (j = 8; j < 16; j++)
	{
		for (i = 4; i < 8; i++)
		{
			s = cvGet2D(src, j, i);
			if (s.val[0] == 255)
				pat.feature[6] += 1.0;
		}
	}
	//第八塊
	for (j = 8; j < 16; j++)
	{
		for (i = 8; i < 12; i++)
		{
			s = cvGet2D(src, j, i);
			if (s.val[0] == 255)
				pat.feature[7] += 1.0;
		}
	}
	//第九塊
	for (j = 8; j < 16; j++)
	{
		for (i = 12; i < 16; i++)
		{
			s = cvGet2D(src, j, i);
			if (s.val[0] == 255)
				pat.feature[8] += 1.0;
		}
	}
	//第十塊
	for (j = 8; j < 16; j++)
	{
		for (i = 16; i < 20; i++)
		{
			s = cvGet2D(src, j, i);
			if (s.val[0] == 255)
				pat.feature[9] += 1.0;
		}
	}
	//********第三行***********
	//第十一塊
	for (j = 16; j < 24; j++)
	{
		for (i = 0; i < 4; i++)
		{
			s = cvGet2D(src, j, i);
			if (s.val[0] == 255)
				pat.feature[10] += 1.0;
		}
	}
	//第十二塊
	for (j = 16; j < 24; j++)
	{
		for (i = 4; i < 8; i++)
		{
			s = cvGet2D(src, j, i);
			if (s.val[0] == 255)
				pat.feature[11] += 1.0;
		}
	}
	//第十三塊
	for (j = 16; j < 24; j++)
	{
		for (i = 8; i < 12; i++)
		{
			s = cvGet2D(src, j, i);
			if (s.val[0] == 255)
				pat.feature[12] += 1.0;
		}
	}
	//第十四塊
	for (j = 16; j < 24; j++)
	{
		for (i = 12; i < 16; i++)
		{
			s = cvGet2D(src, j, i);
			if (s.val[0] == 255)
				pat.feature[13] += 1.0;
		}
	}
	//第十五塊
	for (j = 16; j < 24; j++)
	{
		for (i = 16; i < 20; i++)
		{
			s = cvGet2D(src, j, i);
			if (s.val[0] == 255)
				pat.feature[14] += 1.0;
		}
	}
	//********第四行***********
	//第十六塊
	for (j = 24; j < 32; j++)
	{
		for (i = 0; i < 4; i++)
		{
			s = cvGet2D(src, j, i);
			if (s.val[0] == 255)
				pat.feature[15] += 1.0;
		}
	}
	//第十七塊
	for (j = 24; j < 32; j++)
	{
		for (i = 4; i < 8; i++)
		{
			s = cvGet2D(src, j, i);
			if (s.val[0] == 255)
				pat.feature[16] += 1.0;
		}
	}
	//第十八塊
	for (j = 24; j < 32; j++)
	{
		for (i = 8; i < 12; i++)
		{
			s = cvGet2D(src, j, i);
			if (s.val[0] == 255)
				pat.feature[17] += 1.0;
		}
	}
	//第十九塊
	for (j = 24; j < 32; j++)
	{
		for (i = 12; i < 16; i++)
		{
			s = cvGet2D(src, j, i);
			if (s.val[0] == 255)
				pat.feature[18] += 1.0;
		}
	}
	//第二十塊
	for (j = 24; j < 32; j++)
	{
		for (i = 16; i < 20; i++)
		{
			s = cvGet2D(src, j, i);
			if (s.val[0] == 255)
				pat.feature[19] += 1.0;
		}
	}
	//********第五行***********
	//第二十一塊
	for (j = 32; j < 40; j++)
	{
		for (i = 0; i < 4; i++)
		{
			s = cvGet2D(src, j, i);
			if (s.val[0] == 255)
				pat.feature[20] += 1.0;
		}
	}
	//第二十二塊
	for (j = 32; j < 40; j++)
	{
		for (i = 4; i < 8; i++)
		{
			s = cvGet2D(src, j, i);
			if (s.val[0] == 255)
				pat.feature[21] += 1.0;
		}
	}
	//第二十三塊
	for (j = 32; j < 40; j++)
	{
		for (i = 8; i < 12; i++)
		{
			s = cvGet2D(src, j, i);
			if (s.val[0] == 255)
				pat.feature[22] += 1.0;
		}
	}
	//第二十四塊
	for (j = 32; j < 40; j++)
	{
		for (i = 12; i < 16; i++)
		{
			s = cvGet2D(src, j, i);
			if (s.val[0] == 255)
				pat.feature[23] += 1.0;
		}
	}
	//第二十五塊
	for (j = 32; j < 40; j++)
	{
		for (i = 16; i < 20; i++)
		{
			s = cvGet2D(src, j, i);
			if (s.val[0] == 255)
				pat.feature[24] += 1.0;
		}
	}

	//下面統計方向交點特征
	for (i = 0; i < 20; i++)
	{
		s = cvGet2D(src, 8, i);
		if (s.val[0] == 255)
			pat.feature[25] += 1.0;
	}
	for (i = 0; i < 20; i++)
	{
		s = cvGet2D(src, 16, i);
		if (s.val[0] == 255)
			pat.feature[26] += 1.0;
	}
	for (i = 0; i < 20; i++)
	{
		s = cvGet2D(src, 24, i);
		if (s.val[0] == 255)
			pat.feature[27] += 1.0;
	}
	for (i = 0; i < 20; i++)
	{
		s = cvGet2D(src, 32, i);
		if (s.val[0] == 255)
			pat.feature[28] += 1.0;
	}
	for (j = 0; j < 40; j++)
	{
		s = cvGet2D(src, j, 4);
		if (s.val[0] == 255)
			pat.feature[29] += 1.0;
	}
	for (j = 0; j < 40; j++)
	{
		s = cvGet2D(src, j, 8);
		if (s.val[0] == 255)
			pat.feature[30] += 1.0;
	}
	for (j = 0; j < 40; j++)
	{
		s = cvGet2D(src, j, 12);
		if (s.val[0] == 255)
			pat.feature[31] += 1.0;
	}
	for (j = 0; j < 40; j++)
	{
		s = cvGet2D(src, j, 16);
		if (s.val[0] == 255)
			pat.feature[32] += 1.0;
	}
}


int main()
{

	IplImage * dst_image[7];
	
		dst_image[0]=  cvLoadImage("E:\\LicenseRecognition\\EdgeSearch\\CharacterSeperate\\vertical_0.jpg", 0);
		dst_image[1] = cvLoadImage("E:\\LicenseRecognition\\EdgeSearch\\CharacterSeperate\\vertical_1.jpg", 0);
		dst_image[2] = cvLoadImage("E:\\LicenseRecognition\\EdgeSearch\\CharacterSeperate\\vertical_3.jpg", 0);
		dst_image[3] = cvLoadImage("E:\\LicenseRecognition\\EdgeSearch\\CharacterSeperate\\vertical_4.jpg", 0);
		dst_image[4] = cvLoadImage("E:\\LicenseRecognition\\EdgeSearch\\CharacterSeperate\\vertical_5.jpg", 0);
		dst_image[5] = cvLoadImage("E:\\LicenseRecognition\\EdgeSearch\\CharacterSeperate\\vertical_6.jpg", 0);
		dst_image[6] = cvLoadImage("E:\\LicenseRecognition\\EdgeSearch\\CharacterSeperate\\vertical_7.jpg", 0);

	IplImage * char_sample[34];//字符樣本影像陣列
	IplImage * hanzi_sample[9];//漢字樣本影像陣列
	pattern char_pattern[34];//定義字符樣品庫結構陣列
	pattern hanzi_pattern[9];//定義漢字樣品庫結構陣列
	pattern TestSample[7];//定義待識別字符結構陣列

	//載入字符模板
	char_sample[0] = cvLoadImage("template\\0.bmp", 0);
	char_sample[1] = cvLoadImage("template\\1.bmp", 0);
	char_sample[2] = cvLoadImage("template\\2.bmp", 0);
	char_sample[3] = cvLoadImage("template\\3.bmp", 0);
	char_sample[4] = cvLoadImage("template\\4.bmp", 0);
	char_sample[5] = cvLoadImage("template\\5.bmp", 0);
	char_sample[6] = cvLoadImage("template\\6.bmp", 0);
	char_sample[7] = cvLoadImage("template\\7.bmp", 0);
	char_sample[8] = cvLoadImage("template\\8.bmp", 0);
	char_sample[9] = cvLoadImage("template\\9.bmp", 0);
	char_sample[10] = cvLoadImage("template\\A.bmp", 0);
	char_sample[11] = cvLoadImage("template\\B.bmp", 0);
	char_sample[12] = cvLoadImage("template\\C.bmp", 0);
	char_sample[13] = cvLoadImage("template\\D.bmp", 0);
	char_sample[14] = cvLoadImage("template\\E.bmp", 0);
	char_sample[15] = cvLoadImage("template\\F.bmp", 0);
	char_sample[16] = cvLoadImage("template\\G.bmp", 0);
	char_sample[17] = cvLoadImage("template\\H.bmp", 0);
	char_sample[18] = cvLoadImage("template\\J.bmp", 0);
	char_sample[19] = cvLoadImage("template\\K.bmp", 0);
	char_sample[20] = cvLoadImage("template\\L.bmp", 0);
	char_sample[21] = cvLoadImage("template\\M.bmp", 0);
	char_sample[22] = cvLoadImage("template\\N.bmp", 0);
	char_sample[23] = cvLoadImage("template\\P.bmp", 0);
	char_sample[24] = cvLoadImage("template\\Q.bmp", 0);
	char_sample[25] = cvLoadImage("template\\R.bmp", 0);
	char_sample[26] = cvLoadImage("template\\S.bmp", 0);
	char_sample[27] = cvLoadImage("template\\T.bmp", 0);
	char_sample[28] = cvLoadImage("template\\U.bmp", 0);
	char_sample[29] = cvLoadImage("template\\V.bmp", 0);
	char_sample[30] = cvLoadImage("template\\W.bmp", 0);
	char_sample[31] = cvLoadImage("template\\X.bmp", 0);
	char_sample[32] = cvLoadImage("template\\Y.bmp", 0);
	char_sample[33] = cvLoadImage("template\\Z.bmp", 0);


	//載入漢字模板
	hanzi_sample[0] = cvLoadImage("E:\\LicenseRecognition\\EdgeSearch\\CharacterMatching\\template\\川.bmp", 0);
	hanzi_sample[1] = cvLoadImage("E:\\LicenseRecognition\\EdgeSearch\\CharacterMatching\\template\\鄂.bmp", 0);
	hanzi_sample[2] = cvLoadImage("E:\\LicenseRecognition\\EdgeSearch\\CharacterMatching\\template\\黑.bmp", 0);
	hanzi_sample[3] = cvLoadImage("E:\\LicenseRecognition\\EdgeSearch\\CharacterMatching\\template\\京.bmp", 0);
	hanzi_sample[4] = cvLoadImage("E:\\LicenseRecognition\\EdgeSearch\\CharacterMatching\\template\\遼.bmp", 0);
	hanzi_sample[5] = cvLoadImage("E:\\LicenseRecognition\\EdgeSearch\\CharacterMatching\\template\\瓊.bmp", 0);
	hanzi_sample[6] = cvLoadImage("E:\\LicenseRecognition\\EdgeSearch\\CharacterMatching\\template\\湘.bmp", 0);
	hanzi_sample[7] = cvLoadImage("E:\\LicenseRecognition\\EdgeSearch\\CharacterMatching\\template\\粵.bmp", 0);
	hanzi_sample[8] = cvLoadImage("E:\\LicenseRecognition\\EdgeSearch\\CharacterMatching\\template\\浙.bmp", 0);
	//hanzi_sample[0] = cvLoadImage("E:\\LicenseRecognition\\EdgeSearch\\CharacterMatching\\template\\川a.bmp", 0);
	//hanzi_sample[1] = cvLoadImage("E:\\LicenseRecognition\\EdgeSearch\\CharacterMatching\\template\\鄂a.bmp", 0);
	//hanzi_sample[2] = cvLoadImage("E:\\LicenseRecognition\\EdgeSearch\\CharacterMatching\\template\\黑a.bmp", 0);
	//hanzi_sample[3] = cvLoadImage("E:\\LicenseRecognition\\EdgeSearch\\CharacterMatching\\template\\京a.bmp", 0);
	//hanzi_sample[4] = cvLoadImage("E:\\LicenseRecognition\\EdgeSearch\\CharacterMatching\\template\\遼a.bmp", 0);
	//hanzi_sample[5] = cvLoadImage("E:\\LicenseRecognition\\EdgeSearch\\CharacterMatching\\template\\瓊a.bmp", 0);
	//hanzi_sample[6] = cvLoadImage("E:\\LicenseRecognition\\EdgeSearch\\CharacterMatching\\template\\湘a.bmp", 0);
	//hanzi_sample[7] = cvLoadImage("E:\\LicenseRecognition\\EdgeSearch\\CharacterMatching\\template\\粵a.bmp", 0);
	//hanzi_sample[8] = cvLoadImage("E:\\LicenseRecognition\\EdgeSearch\\CharacterMatching\\template\\浙a.bmp", 0);	
	//hanzi_sample[9] = cvLoadImage("E:\\LicenseRecognition\\EdgeSearch\\CharacterMatching\\template\\蘇a.bmp", 0);
	//hanzi_sample[10] = cvLoadImage("E:\\LicenseRecognition\\EdgeSearch\\CharacterMatching\\template\\藏a.bmp", 0);
	//hanzi_sample[11] = cvLoadImage("E:\\LicenseRecognition\\EdgeSearch\\CharacterMatching\\template\\甘a.bmp", 0);
	//hanzi_sample[12] = cvLoadImage("E:\\LicenseRecognition\\EdgeSearch\\CharacterMatching\\template\\贛a.bmp", 0);
	//hanzi_sample[13] = cvLoadImage("E:\\LicenseRecognition\\EdgeSearch\\CharacterMatching\\template\\桂a.bmp", 0);
	//hanzi_sample[14] = cvLoadImage("E:\\LicenseRecognition\\EdgeSearch\\CharacterMatching\\template\\滬a.bmp", 0);
	//hanzi_sample[15] = cvLoadImage("E:\\LicenseRecognition\\EdgeSearch\\CharacterMatching\\template\\吉a.bmp", 0);
	//hanzi_sample[16] = cvLoadImage("E:\\LicenseRecognition\\EdgeSearch\\CharacterMatching\\template\\冀a.bmp", 0);
	//hanzi_sample[17] = cvLoadImage("E:\\LicenseRecognition\\EdgeSearch\\CharacterMatching\\template\\津a.bmp", 0);
	//hanzi_sample[18] = cvLoadImage("E:\\LicenseRecognition\\EdgeSearch\\CharacterMatching\\template\\晉a.bmp", 0);
	//hanzi_sample[19] = cvLoadImage("E:\\LicenseRecognition\\EdgeSearch\\CharacterMatching\\template\\魯a.bmp", 0);
	//hanzi_sample[20] = cvLoadImage("E:\\LicenseRecognition\\EdgeSearch\\CharacterMatching\\template\\蒙a.bmp", 0);
	//hanzi_sample[21] = cvLoadImage("E:\\LicenseRecognition\\EdgeSearch\\CharacterMatching\\template\\閩a.bmp", 0);
	//hanzi_sample[22] = cvLoadImage("E:\\LicenseRecognition\\EdgeSearch\\CharacterMatching\\template\\寧a.bmp", 0);
	//hanzi_sample[23] = cvLoadImage("E:\\LicenseRecognition\\EdgeSearch\\CharacterMatching\\template\\青a.bmp", 0);
	//hanzi_sample[24] = cvLoadImage("E:\\LicenseRecognition\\EdgeSearch\\CharacterMatching\\template\\陜a.bmp", 0);
	//hanzi_sample[25] = cvLoadImage("E:\\LicenseRecognition\\EdgeSearch\\CharacterMatching\\template\\皖a.bmp", 0);
	//hanzi_sample[26] = cvLoadImage("E:\\LicenseRecognition\\EdgeSearch\\CharacterMatching\\template\\新a.bmp", 0);
	//hanzi_sample[27] = cvLoadImage("E:\\LicenseRecognition\\EdgeSearch\\CharacterMatching\\template\\渝a.bmp", 0);
	//hanzi_sample[28] = cvLoadImage("E:\\LicenseRecognition\\EdgeSearch\\CharacterMatching\\template\\豫a.bmp", 0);
	//hanzi_sample[29] = cvLoadImage("E:\\LicenseRecognition\\EdgeSearch\\CharacterMatching\\template\\云a.bmp", 0);


	//提取字符樣本特征
	for (int i = 0; i < 34; i++)
	{
		GetFeature(char_sample[i], char_pattern[i]);
	}
	//提取漢字字符特征
	for (int i = 0; i < 9; i++)
	{
		GetFeature(hanzi_sample[i], hanzi_pattern[i]);
	}
	//提取待識別字符特征
	for (int i = 0; i < 7; i++)
	{
		GetFeature(dst_image[i], TestSample[i]);
	}

	//進行模板匹配	
	double min = 100000.0;
	for (int num = 0; num < 1; num++)
	{
		for (int i = 0; i < 9; i++)
		{
			double diff = 0.0;
			for (int j = 0; j < 25; j++)
			{
				diff += fabs(TestSample[num].feature[j] - hanzi_pattern[i].feature[j]);
			}
			for (int j = 25; j < 33; j++)
			{
				diff += fabs(TestSample[num].feature[j] - hanzi_pattern[i].feature[j]) * 9;
			}
			if (diff < min)
			{
				min = diff;
				TestSample[num].number = i;
			}
		}
	}

	for (int num = 1; num < 7; num++)
	{
		double min_min = 1000000.0;
		for (int i = 0; i < 34; i++)
		{
			double diff_diff = 0.0;
			for (int j = 0; j < 25; j++)
			{
				diff_diff += fabs(TestSample[num].feature[j] - char_pattern[i].feature[j]);
			}
			for (int j = 25; j < 33; j++)
			{
				diff_diff += fabs(TestSample[num].feature[j] - char_pattern[i].feature[j]);
			}
			if (diff_diff < min_min)
			{
				min_min = diff_diff;
				TestSample[num].number = i;
			}
		}
	}

	String result = "";//存放識別出的字符

	for (int i = 0; i < 1; i++)
	{
		switch (TestSample[i].number)
		{
		case 0:
			result += "川";
			break;
		case 1:
			result += "鄂";
			break;
		case 2:
			result += "黑";
			break;
		case 3:
			result += "京";
			break;
		case 4:
			result += "遼";
			break;
		case 5:
			result += "瓊";
			break;
		case 6:
			result += "湘";
			break;
		case 7:
			result += "粵";
			break;
		case 8:
			result += "浙";
			break;
		default:
			cout<<("識別失敗")<<endl;
			break;
		}
	}

	for (int i = 1; i < 7; i++)
	{
		switch (TestSample[i].number)
		{
		case 0:
			result += "0";
			break;
		case 1:
			result += "1";
			break;
		case 2:
			result += "2";
			break;
		case 3:
			result += "3";
			break;
		case 4:
			result += "4";
			break;
		case 5:
			result += "6";
			break;
		case 6:
			result += "5";
			break;
		case 7:
			result += "7";
			break;
		case 8:
			result += "B";
			break;
		case 9:
			result += "9";
			break;
		case 10:
			result += "A";
			break;
		case 11:
			result += "8";
			break;
		case 12:
			result += "C";
			break;
		case 13:
			result += "D";
			break;
		case 14:
			result += "E";;
			break;
		case 15:
			result += "F";
		case 16:
			result += "G";
			break;
		case 17:
			result += "H";
			break;
		case 18:
			result += "J";
			break;
		case 19:
			result += "K";
			break;
		case 20:
			result += "L";
			break;
		case 21:
			result += "M";
			break;
		case 22:
			result += "N";
			break;
		case 23:
			result += "P";
			break;
		case 24:
			result += "Q";
			break;
		case 25:
			result += "R";
			break;
		case 26:
			result += "S";
			break;
		case 27:
			result += "T";
			break;
		case 28:
			result += "U";
			break;
		case 29:
			result += "U";
			break;
		case 30:
			result += "W";
			break;
		case 31:
			result += "X";
			break;
		case 32:
			result += "Y";
			break;
		case 33:
			result += "Z";
			break;
		default:
			cout<<("識別失敗");
			break;
		}
	}
	cout<<"車牌的最終結果為:"<<result<<endl;//顯示結果
	system("pause");
	return 0;
}

需要template模板,網上下載即可
模板

結果效果:效果圖

五、總結

特別感謝CSDN博主吾理小子、CSDN博主Nine-days、CSDN博主lxx_123456等
也感謝CSDN全體制作OpenCV車牌識別有關博客的博主,為此博客奠定了知識基礎,此博客僅供學習使用,希望可以給著急于做出車牌識別的朋友一點靈感,不足之處可以指出,如對讀者朋友們有用,希望可以點個贊,

六、感悟

這是我第一次通過觀摩借鑒復用各位CSDN大佬們的博客文章以及開源代碼整合而成的專案,算是我代碼路上一個開始,自此逐漸擺脫了拘泥于書本知識而非親身實踐的學習惡習,搞車牌識別專案的時候會遇到很多很多困難與疑惑,通過找博客和參考其他博主的經驗和教訓來解決自己的困難,比起我之前遇到困難就退縮,只想白嫖成果要好千萬倍(雖然這個也白嫖了很多),希望可以和CSDN上的兄弟們一起進步共同加油!

轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/73047.html

標籤:區塊鏈

上一篇:ipad8和ipad mini5哪個好

下一篇:如何批量下載B站視頻(下載整個串列)——學習黨get起來!

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • JAVA使用 web3j 進行token轉賬

    最近新學習了下區塊鏈這方面的知識,所學不多,給大家分享下。 # 1. 關于web3j web3j是一個高度模塊化,反應性,型別安全的Java和Android庫,用于與智能合約配合并與以太坊網路上的客戶端(節點)集成。 # 2. 準備作業 jdk版本1.8 引入maven <dependency> < ......

    uj5u.com 2020-09-10 03:03:06 more
  • 以太坊智能合約開發框架Truffle

    前言 部署智能合約有多種方式,命令列的瀏覽器的渠道都有,但往往跟我們程式員的風格不太相符,因為我們習慣了在IDE里寫了代碼然后打包運行看效果。 雖然現在IDE中已經存在了Solidity插件,可以撰寫智能合約,但是部署智能合約卻要另走他路,沒辦法進行一個快捷的部署與測驗。 如果團隊管理的區塊節點多、 ......

    uj5u.com 2020-09-10 03:03:12 more
  • 谷歌二次驗證碼成為區塊鏈專用安全碼,你怎么看?

    前言 谷歌身份驗證器,前些年大家都比較陌生,但隨著國內互聯網安全的加強,它越來越多地出現在大家的視野中。 比較廣泛接觸的人群是國際3A游戲愛好者,游戲盜號現象嚴重+國外賬號安全應用廣泛,這類游戲一般都會要求用戶系結名為“兩步驗證”、“雙重驗證”等,平臺一般都推薦用谷歌身份驗證器。 后來區塊鏈業務風靡 ......

    uj5u.com 2020-09-10 03:03:17 more
  • 密碼學DAY1

    目錄 ##1.1 密碼學基本概念 密碼在我們的生活中有著重要的作用,那么密碼究竟來自何方,為何會產生呢? 密碼學是網路安全、資訊安全、區塊鏈等產品的基礎,常見的非對稱加密、對稱加密、散列函式等,都屬于密碼學范疇。 密碼學有數千年的歷史,從最開始的替換法到如今的非對稱加密演算法,經歷了古典密碼學,近代密 ......

    uj5u.com 2020-09-10 03:03:50 more
  • 密碼學DAY1_02

    目錄 ##1.1 ASCII編碼 ASCII(American Standard Code for Information Interchange,美國資訊交換標準代碼)是基于拉丁字母的一套電腦編碼系統,主要用于顯示現代英語和其他西歐語言。它是現今最通用的單位元組編碼系統,并等同于國際標準ISO/IE ......

    uj5u.com 2020-09-10 03:04:50 more
  • 密碼學DAY2

    ##1.1 加密模式 加密模式:https://docs.oracle.com/javase/8/docs/api/javax/crypto/Cipher.html ECB ECB : Electronic codebook, 電子密碼本. 需要加密的訊息按照塊密碼的塊大小被分為數個塊,并對每個塊進 ......

    uj5u.com 2020-09-10 03:05:42 more
  • NTP時鐘服務器的特點(京準電子)

    NTP時鐘服務器的特點(京準電子) NTP時鐘服務器的特點(京準電子) 京準電子官V——ahjzsz 首先對時間同步進行了背景介紹,然后討論了不同的時間同步網路技術,最后指出了建立全球或區域時間同步網存在的問題。 一、概 述 在通信領域,“同步”概念是指頻率的同步,即網路各個節點的時鐘頻率和相位同步 ......

    uj5u.com 2020-09-10 03:05:47 more
  • 標準化考場時鐘同步系統推進智能化校園建設

    標準化考場時鐘同步系統推進智能化校園建設 標準化考場時鐘同步系統推進智能化校園建設 安徽京準電子科技官微——ahjzsz 一、背景概述隨著教育事業的快速發展,學校建設如雨后春筍,隨之而來的學校教育、管理、安全方面的問題成了學校管理人員面臨的最大的挑戰,這些問題同時也是學生家長所擔心的。為了讓學生有更 ......

    uj5u.com 2020-09-10 03:05:51 more
  • 位元幣入門

    引言 位元幣基本結構 位元幣基礎知識 1)哈希演算法 2)非對稱加密技術 3)數字簽名 4)MerkleTree 5)哪有位元幣,有的是UTXO 6)位元幣挖礦與共識 7)區塊驗證(共識) 總結 引言 上一篇我們已經知道了什么是區塊鏈,此篇說一下區塊鏈的第一個應用——位元幣。其實先有位元幣,后有的區塊 ......

    uj5u.com 2020-09-10 03:06:15 more
  • 北斗對時服務器(北斗對時設備)電力系統應用

    北斗對時服務器(北斗對時設備)電力系統應用 北斗對時服務器(北斗對時設備)電力系統應用 京準電子科技官微(ahjzsz) 中國北斗衛星導航系統(英文名稱:BeiDou Navigation Satellite System,簡稱BDS),因為是目前世界范圍內唯一可以大面積提供免費定位服務的系統,所以 ......

    uj5u.com 2020-09-10 03:06:20 more
最新发布
  • web3 產品介紹:metamask 錢包 使用最多的瀏覽器插件錢包

    Metamask錢包是一種基于區塊鏈技術的數字貨幣錢包,它允許用戶在安全、便捷的環境下管理自己的加密資產。Metamask錢包是以太坊生態系統中最流行的錢包之一,它具有易于使用、安全性高和功能強大等優點。 本文將詳細介紹Metamask錢包的功能和使用方法。 一、 Metamask錢包的功能 數字資 ......

    uj5u.com 2023-04-20 08:46:47 more
  • Hyperledger Fabric 使用 CouchDB 和復雜智能合約開發

    在上個實驗中,我們已經實作了簡單智能合約實作及客戶端開發,但該實驗中智能合約只有基礎的增刪改查功能,且其中的資料管理功能與傳統 MySQL 比相差甚遠。本文將在前面實驗的基礎上,將 Hyperledger Fabric 的默認資料庫支持 LevelDB 改為 CouchDB 模式,以實作更復雜的資料... ......

    uj5u.com 2023-04-16 07:28:31 more
  • .NET Core 波場鏈離線簽名、廣播交易(發送 TRX和USDT)筆記

    Get Started NuGet You can run the following command to install the Tron.Wallet.Net in your project. PM> Install-Package Tron.Wallet.Net 配置 public reco ......

    uj5u.com 2023-04-14 08:08:00 more
  • DKP 黑客分析——不正確的代幣對比率計算

    概述: 2023 年 2 月 8 日,針對 DKP 協議的閃電貸攻擊導致該協議的用戶損失了 8 萬美元,因為 execute() 函式取決于 USDT-DKP 對中兩種代幣的余額比率。 智能合約黑客概述: 攻擊者的交易:0x0c850f,0x2d31 攻擊者地址:0xF38 利用合同:0xf34ad ......

    uj5u.com 2023-04-07 07:46:09 more
  • Defi開發簡介

    Defi開發簡介 介紹 Defi是去中心化金融的縮寫, 是一項旨在利用區塊鏈技術和智能合約創建更加開放,可訪問和透明的金融體系的運動. 這與傳統金融形成鮮明對比,傳統金融通常由少數大型銀行和金融機構控制 在Defi的世界里,用戶可以直接從他們的電腦或移動設備上訪問廣泛的金融服務,而不需要像銀行或者信 ......

    uj5u.com 2023-04-05 08:01:34 more
  • solidity簡單的ERC20代幣實作

    // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.7.0 <0.9.0; import "hardhat/console.sol"; //ERC20 同質化代幣,每個代幣的本質或性質都是相同 //ETH 是原生代幣,它不是ERC20代幣, ......

    uj5u.com 2023-03-21 07:56:29 more
  • solidity 參考型別修飾符memory、calldata與storage 常量修飾符C

    在solidity語言中 參考型別修飾符(參考型別為存盤空間不固定的數值型別) memory、calldata與storage,它們只能修飾參考型別變數,比如字串、陣列、位元組等... memory 適用于方法傳參、返參或在方法體內使用,使用完就會清除掉,釋放記憶體 calldata 僅適用于方法傳參 ......

    uj5u.com 2023-03-08 07:57:54 more
  • solidity注解標簽

    在solidity語言中 注釋符為// 注解符為/* 內容*/ 或者 是 ///內容 注解中含有這幾個標簽給予我們使用 @title 一個應該描述合約/介面的標題 contract, library, interface @author 作者的名字 contract, library, interf ......

    uj5u.com 2023-03-08 07:57:49 more
  • 評價指標:相似度、GAS消耗

    【代碼注釋自動生成方法綜述】 這些評測指標主要來自機器翻譯和文本總結等研究領域,可以評估候選文本(即基于代碼注釋自動方法而生成)和參考文本(即基于手工方式而生成)的相似度. BLEU指標^[^?88^^?^]^:其全稱是bilingual evaluation understudy.該指標是最早用于 ......

    uj5u.com 2023-02-23 07:27:39 more
  • 基于NOSTR協議的“公有制”版本的Twitter,去中心化社交軟體Damus

    最近,一個幽靈,Web3的幽靈,在網路游蕩,它叫Damus,這玩意詮釋了什么叫做病毒式營銷,滑稽的是,一個Web3產品卻在Web2的產品鏈上瘋狂傳銷,各方大佬紛紛為其背書,到底發生了什么?Damus的葫蘆里,賣的是什么藥? 注冊和簡單實用 很少有什么產品在用戶注冊環節會有什么噱頭,但Damus確實出 ......

    uj5u.com 2023-02-05 06:48:39 more