opencv 案例实战02-停车场车牌识别SVM模型训练及验证

news2024/11/17 11:37:01

1. 整个识别的流程图:

在这里插入图片描述
2. 车牌定位中分割流程图:

在这里插入图片描述
三、车牌识别中字符分割流程图:

在这里插入图片描述

1.准备数据集

下载车牌相关字符样本用于训练和测试,本文使用14个汉字样本和34个数字跟字母样本,每个字符样本数为40,样本尺寸为28*28。

在这里插入图片描述

在这里插入图片描述
数据集下载地址

https://download.csdn.net/download/hai411741962/88248392

下载不了,评论区留言
2. 编码训练代码

import cv2
import numpy as np
from numpy.linalg import norm
import sys
import os
import json

SZ = 20          #训练图片长宽
MAX_WIDTH = 1000 #原始图片最大宽度
Min_Area = 2000  #车牌区域允许最大面积
PROVINCE_START = 1000
#不能保证包括所有省份
provinces = [
	"zh_cuan", "川",
	"zh_e", "鄂",
	"zh_gan", "赣",
	"zh_gan1", "甘",
	"zh_gui", "贵",
	"zh_gui1", "桂",
	"zh_hei", "黑",
	"zh_hu", "沪",
	"zh_ji", "冀",
	"zh_jin", "津",
	"zh_jing", "京",
	"zh_jl", "吉",
	"zh_liao", "辽",
	"zh_lu", "鲁",
	"zh_meng", "蒙",
	"zh_min", "闽",
	"zh_ning", "宁",
	"zh_qing", "靑",
	"zh_qiong", "琼",
	"zh_shan", "陕",
	"zh_su", "苏",
	"zh_sx", "晋",
	"zh_wan", "皖",
	"zh_xiang", "湘",
	"zh_xin", "新",
	"zh_yu", "豫",
	"zh_yu1", "渝",
	"zh_yue", "粤",
	"zh_yun", "云",
	"zh_zang", "藏",
	"zh_zhe", "浙"
]

class StatModel(object):
	def load(self, fn):
		self.model = self.model.load(fn)#从文件载入训练好的模型
	def save(self, fn):
		self.model.save(fn)#保存训练好的模型到文件中

class SVM(StatModel):
	def __init__(self, C = 1, gamma = 0.5):
		self.model = cv2.ml.SVM_create()#生成一个SVM模型
		self.model.setGamma(gamma) #设置Gamma参数,demo中是0.5
		self.model.setC(C)# 设置惩罚项, 为:1
		self.model.setKernel(cv2.ml.SVM_RBF)#设置核函数
		self.model.setType(cv2.ml.SVM_C_SVC)#设置SVM的模型类型:SVC是分类模型,SVR是回归模型
	#训练svm
	def train(self, samples, responses):
		self.model.train(samples, cv2.ml.ROW_SAMPLE, responses)#训练
	#字符识别
	def predict(self, samples):
		r = self.model.predict(samples)#预测
		return r[1].ravel()

#来自opencv的sample,用于svm训练
def deskew(img):
	m = cv2.moments(img)
	if abs(m['mu02']) < 1e-2:
		return img.copy()
	skew = m['mu11']/m['mu02']
	M = np.float32([[1, skew, -0.5*SZ*skew], [0, 1, 0]])
	img = cv2.warpAffine(img, M, (SZ, SZ), flags=cv2.WARP_INVERSE_MAP | cv2.INTER_LINEAR)
	return img

#来自opencv的sample,用于svm训练
def preprocess_hog(digits):
	samples = []
	for img in digits:
		gx = cv2.Sobel(img, cv2.CV_32F, 1, 0)
		gy = cv2.Sobel(img, cv2.CV_32F, 0, 1)
		mag, ang = cv2.cartToPolar(gx, gy)
		bin_n = 16
		bin = np.int32(bin_n*ang/(2*np.pi))
		bin_cells = bin[:10,:10], bin[10:,:10], bin[:10,10:], bin[10:,10:]
		mag_cells = mag[:10,:10], mag[10:,:10], mag[:10,10:], mag[10:,10:]
		hists = [np.bincount(b.ravel(), m.ravel(), bin_n) for b, m in zip(bin_cells, mag_cells)]
		hist = np.hstack(hists)

		# transform to Hellinger kernel
		eps = 1e-7
		hist /= hist.sum() + eps
		hist = np.sqrt(hist)
		hist /= norm(hist) + eps

		samples.append(hist)
	return np.float32(samples)


def save_traindata(model,modelchinese):
	if not os.path.exists("module\\svm.dat"):
		model.save("module\\svm.dat")
	if not os.path.exists("module\\svmchinese.dat"):
		modelchinese.save("module\\svmchinese.dat")

def train_svm():
	#识别英文字母和数字
	model = SVM(C=1, gamma=0.5)
	#识别中文
	modelchinese = SVM(C=1, gamma=0.5)
	if os.path.exists("svm.dat"):
		model.load("svm.dat")
	else:
		chars_train = []
		chars_label = []

		for root, dirs, files in os.walk("train\\chars2"):
			if len(os.path.basename(root)) > 1:
				continue
			root_int = ord(os.path.basename(root))
			for filename in files:
				filepath = os.path.join(root,filename)
				digit_img = cv2.imread(filepath)
				digit_img = cv2.cvtColor(digit_img, cv2.COLOR_BGR2GRAY)
				chars_train.append(digit_img)
				#chars_label.append(1)
				chars_label.append(root_int)

		chars_train = list(map(deskew, chars_train))
		#print(chars_train)
		chars_train = preprocess_hog(chars_train)
		#print(chars_train)
		#chars_train = chars_train.reshape(-1, 20, 20).astype(np.float32)
		chars_label = np.array(chars_label)
		model.train(chars_train, chars_label)
	if os.path.exists("svmchinese.dat"):
		modelchinese.load("svmchinese.dat")
	else:
		chars_train = []
		chars_label = []
		for root, dirs, files in os.walk("train\\charsChinese"):
			if not os.path.basename(root).startswith("zh_"):
				continue
			pinyin = os.path.basename(root)
			index = provinces.index(pinyin) + PROVINCE_START + 1 #1是拼音对应的汉字
			for filename in files:
				filepath = os.path.join(root,filename)
				digit_img = cv2.imread(filepath)
				digit_img = cv2.cvtColor(digit_img, cv2.COLOR_BGR2GRAY)
				chars_train.append(digit_img)
				#chars_label.append(1)
				chars_label.append(index)
		chars_train = list(map(deskew, chars_train))
		chars_train = preprocess_hog(chars_train)
		#chars_train = chars_train.reshape(-1, 20, 20).astype(np.float32)
		chars_label = np.array(chars_label)
		print(chars_train.shape)
		modelchinese.train(chars_train, chars_label)

	save_traindata(model,modelchinese)


train_svm()

运行代码后会生成两个模型文件,下面验证两个模型文件。

在这里插入图片描述

import cv2
import numpy as np

import json
import train

SZ = 20          #训练图片长宽
MAX_WIDTH = 1000 #原始图片最大宽度
Min_Area = 2000  #车牌区域允许最大面积
PROVINCE_START = 1000
#读取图片文件
def imreadex(filename):
	return cv2.imdecode(np.fromfile(filename, dtype=np.uint8), cv2.IMREAD_COLOR)

def point_limit(point):
	if point[0] < 0:
		point[0] = 0
	if point[1] < 0:
		point[1] = 0

#根据设定的阈值和图片直方图,找出波峰,用于分隔字符
def find_waves(threshold, histogram):
	up_point = -1#上升点
	is_peak = False
	if histogram[0] > threshold:
		up_point = 0
		is_peak = True
	wave_peaks = []
	for i,x in enumerate(histogram):
		if is_peak and x < threshold:
			if i - up_point > 2:
				is_peak = False
				wave_peaks.append((up_point, i))
		elif not is_peak and x >= threshold:
			is_peak = True
			up_point = i
	if is_peak and up_point != -1 and i - up_point > 4:
		wave_peaks.append((up_point, i))
	return wave_peaks

#根据找出的波峰,分隔图片,从而得到逐个字符图片
def seperate_card(img, waves):
	part_cards = []
	for wave in waves:
		part_cards.append(img[:, wave[0]:wave[1]])
	return part_cards

class CardPredictor:
	def __init__(self):
		#车牌识别的部分参数保存在json中,便于根据图片分辨率做调整
		f = open('config.json')
		j = json.load(f)
		for c in j["config"]:
			if c["open"]:
				self.cfg = c.copy()
				break
		else:
			raise RuntimeError('没有设置有效配置参数')


	def load_svm(self):
		#识别英文字母和数字
		self.model = train.SVM(C=1, gamma=0.5)#SVM(C=1, gamma=0.5)
		#识别中文
		self.modelchinese = train.SVM(C=1, gamma=0.5)#SVM(C=1, gamma=0.5)
		self.model.load("module\\svm.dat")
		self.modelchinese.load("module\\svmchinese.dat")


	def accurate_place(self, card_img_hsv, limit1, limit2, color):
		row_num, col_num = card_img_hsv.shape[:2]
		xl = col_num
		xr = 0
		yh = 0
		yl = row_num
		#col_num_limit = self.cfg["col_num_limit"]
		row_num_limit = self.cfg["row_num_limit"]
		col_num_limit = col_num * 0.8 if color != "green" else col_num * 0.5#绿色有渐变
		for i in range(row_num):
			count = 0
			for j in range(col_num):
				H = card_img_hsv.item(i, j, 0)
				S = card_img_hsv.item(i, j, 1)
				V = card_img_hsv.item(i, j, 2)
				if limit1 < H <= limit2 and 34 < S and 46 < V:
					count += 1
			if count > col_num_limit:
				if yl > i:
					yl = i
				if yh < i:
					yh = i
		for j in range(col_num):
			count = 0
			for i in range(row_num):
				H = card_img_hsv.item(i, j, 0)
				S = card_img_hsv.item(i, j, 1)
				V = card_img_hsv.item(i, j, 2)
				if limit1 < H <= limit2 and 34 < S and 46 < V:
					count += 1
			if count > row_num - row_num_limit:
				if xl > j:
					xl = j
				if xr < j:
					xr = j
		return xl, xr, yh, yl

	def predict(self, car_pic, resize_rate=1):
		if type(car_pic) == type(""):
			img = imreadex(car_pic)
		else:
			img = car_pic
		pic_hight, pic_width = img.shape[:2]

		if resize_rate != 1:
			img = cv2.resize(img, (int(pic_width*resize_rate), int(pic_hight*resize_rate)), interpolation=cv2.INTER_AREA)
			pic_hight, pic_width = img.shape[:2]
		#cv2.imshow('img',img)
		#cv2.waitKey(0)
		print("h,w:", pic_hight, pic_width)
		blur = self.cfg["blur"]
		#高斯去噪
		if blur > 0:
			img = cv2.GaussianBlur(img, (blur, blur), 0)#图片分辨率调整
		oldimg = img
		img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

		#去掉图像中不会是车牌的区域
		kernel = np.ones((20, 20), np.uint8)
		img_opening = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)
		img_opening = cv2.addWeighted(img, 1, img_opening, -1, 0);

		#找到图像边缘
		ret, img_thresh = cv2.threshold(img_opening, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
		img_edge = cv2.Canny(img_thresh, 100, 200)#边缘检测

		#使用开运算和闭运算让图像边缘成为一个整体
		kernel = np.ones((self.cfg["morphologyr"], self.cfg["morphologyc"]), np.uint8)
		img_edge1 = cv2.morphologyEx(img_edge, cv2.MORPH_CLOSE, kernel)

		img_edge2 = cv2.morphologyEx(img_edge1, cv2.MORPH_OPEN, kernel)

		#查找图像边缘整体形成的矩形区域,可能有很多,车牌就在其中一个矩形区域中
		contours, hierarchy = cv2.findContours(img_edge2, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
		print('len(contours)', len(contours))#找出区域
		contours = [cnt for cnt in contours if cv2.contourArea(cnt) > Min_Area]
		print('len(contours)', len(contours))#cv2.contourArea计算面积
		#一一排除不是车牌的矩形区域
		car_contours = []
		for cnt in contours:
			rect = cv2.minAreaRect(cnt)#minAreaRect
			area_width, area_height = rect[1]
			if area_width < area_height:
				area_width, area_height = area_height, area_width
			wh_ratio = area_width / area_height#长宽比
			#print(wh_ratio)
			#要求矩形区域长宽比在25.5之间,25.5是车牌的长宽比,其余的矩形排除
			if wh_ratio > 2 and wh_ratio < 5.5:
				car_contours.append(rect)
				box = cv2.boxPoints(rect)#cv2.boxPoints()可获取该矩形的四个顶点坐标。
				print(box)
				box = np.int0(box) #转成整数
				print(box)
			oldimg = cv2.drawContours(oldimg, [box], 0, (0, 0, 255), 2)
			
		print(len(car_contours))

		print("精确定位")
		card_imgs = []
		#矩形区域可能是倾斜的矩形,需要矫正,以便使用颜色定位
		for rect in car_contours:
			if rect[2] > -1 and rect[2] < 1:#创造角度,使得左、高、右、低拿到正确的值
				angle = 1
			else:
				angle = rect[2]
			rect = (rect[0], (rect[1][0]+5, rect[1][1]+5), angle)#扩大范围,避免车牌边缘被排除

			box = cv2.boxPoints(rect)
			heigth_point = right_point = [0, 0]
			left_point = low_point = [pic_width, pic_hight]
			for point in box:
				if left_point[0] > point[0]:
					left_point = point
				if low_point[1] > point[1]:
					low_point = point
				if heigth_point[1] < point[1]:
					heigth_point = point
				if right_point[0] < point[0]:
					right_point = point

			if left_point[1] <= right_point[1]:#正角度
				new_right_point = [right_point[0], heigth_point[1]]
				pts2 = np.float32([left_point, heigth_point, new_right_point])#字符只是高度需要改变
				pts1 = np.float32([left_point, heigth_point, right_point])
				M = cv2.getAffineTransform(pts1, pts2)
				dst = cv2.warpAffine(oldimg, M, (pic_width, pic_hight))
				point_limit(new_right_point)
				point_limit(heigth_point)
				point_limit(left_point)
				card_img = dst[int(left_point[1]):int(heigth_point[1]), int(left_point[0]):int(new_right_point[0])]
				if(len(card_img)>0):
					card_imgs.append(card_img)

			elif left_point[1] > right_point[1]:#负角度

				new_left_point = [left_point[0], heigth_point[1]]
				pts2 = np.float32([new_left_point, heigth_point, right_point])#字符只是高度需要改变
				pts1 = np.float32([left_point, heigth_point, right_point])
				M = cv2.getAffineTransform(pts1, pts2)
				dst = cv2.warpAffine(oldimg, M, (pic_width, pic_hight))
				point_limit(right_point)
				point_limit(heigth_point)
				point_limit(new_left_point)
				card_img = dst[int(right_point[1]):int(heigth_point[1]), int(new_left_point[0]):int(right_point[0])]
				
				card_imgs.append(card_img)
			#cv2.imshow("card", card_img)
			#cv2.waitKey(0)
		#开始使用颜色定位,排除不是车牌的矩形,目前只识别蓝、绿、黄车牌
		colors = []
		for card_index,card_img in enumerate(card_imgs):
			print(len(card_imgs))
			green = yello = blue = black = white = 0
			card_img_hsv = cv2.cvtColor(card_img, cv2.COLOR_BGR2HSV)
			print("card_img_hsv.shape")
			print(card_img_hsv.shape)
			#有转换失败的可能,原因来自于上面矫正矩形出错
			if card_img_hsv is None:
				continue
			row_num, col_num= card_img_hsv.shape[:2]
			card_img_count = row_num * col_num

			for i in range(row_num):
				for j in range(col_num):
					H = card_img_hsv.item(i, j, 0)
					S = card_img_hsv.item(i, j, 1)
					V = card_img_hsv.item(i, j, 2)
					if 11 < H <= 34 and S > 34:#图片分辨率调整
						yello += 1
					elif 35 < H <= 99 and S > 34:#图片分辨率调整
						green += 1
					elif 99 < H <= 124 and S > 34:#图片分辨率调整
						blue += 1

					if 0 < H <180 and 0 < S < 255 and 0 < V < 46:
						black += 1
					elif 0 < H <180 and 0 < S < 43 and 221 < V < 225:
						white += 1
			color = "no"
            #根据HSV判断车牌颜色
			limit1 = limit2 = 0
			if yello*2 >= card_img_count:
				color = "yello"
				limit1 = 11
				limit2 = 34#有的图片有色偏偏绿
			elif green*2 >= card_img_count:
				color = "green"
				limit1 = 35
				limit2 = 99
			elif blue*2 >= card_img_count:
				color = "blue"
				limit1 = 100
				limit2 = 124#有的图片有色偏偏紫
			elif black + white >= card_img_count*0.7:#TODO
				color = "bw"

			colors.append(color)
			print("blue, green, yello, black, white, card_img_count:")
			print(blue,"   " ,green,"   ", yello,"   ", black,"   ", white,"   ", card_img_count)
			print("车牌颜色:",color)
			# cv2.imshow("color", card_img)
			# cv2.waitKey(0)
			if limit1 == 0:
				continue
			#以上为确定车牌颜色
			#以下为根据车牌颜色再定位,缩小边缘非车牌边界
			xl, xr, yh, yl = self.accurate_place(card_img_hsv, limit1, limit2, color)
			if yl == yh and xl == xr:
				continue
			need_accurate = False
			if yl >= yh:
				yl = 0
				yh = row_num
				need_accurate = True
			if xl >= xr:
				xl = 0
				xr = col_num
				need_accurate = True
			card_imgs[card_index] = card_img[yl:yh, xl:xr] if color != "green" or yl < (yh-yl)//4 else card_img[yl-(yh-yl)//4:yh, xl:xr]
			if need_accurate:#可能x或y方向未缩小,需要再试一次
				card_img = card_imgs[card_index]
				card_img_hsv = cv2.cvtColor(card_img, cv2.COLOR_BGR2HSV)
				xl, xr, yh, yl = self.accurate_place(card_img_hsv, limit1, limit2, color)
				if yl == yh and xl == xr:
					continue
				if yl >= yh:
					yl = 0
					yh = row_num
				if xl >= xr:
					xl = 0
					xr = col_num
			card_imgs[card_index] = card_img[yl:yh, xl:xr] if color != "green" or yl < (yh-yl)//4 else card_img[yl-(yh-yl)//4:yh, xl:xr]
		#以上为车牌定位
		#以下为识别车牌中的字符
		predict_result = []
		roi = None
		card_color = None
		for i, color in enumerate(colors):
			if color in ("blue", "yello", "green"):
				card_img = card_imgs[i]
			
				gray_img = cv2.cvtColor(card_img, cv2.COLOR_BGR2GRAY)
			
				#黄、绿车牌字符比背景暗、与蓝车牌刚好相反,所以黄、绿车牌需要反向
				if color == "green" or color == "yello":
					gray_img = cv2.bitwise_not(gray_img)
				ret, gray_img = cv2.threshold(gray_img, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
				#查找水平直方图波峰
				x_histogram  = np.sum(gray_img, axis=1)
				x_min = np.min(x_histogram)
				x_average = np.sum(x_histogram)/x_histogram.shape[0]
				x_threshold = (x_min + x_average)/2
				wave_peaks = find_waves(x_threshold, x_histogram)
				if len(wave_peaks) == 0:
					print("peak less 0:")
					continue
				#认为水平方向,最大的波峰为车牌区域
				wave = max(wave_peaks, key=lambda x:x[1]-x[0])
				gray_img = gray_img[wave[0]:wave[1]]
				#查找垂直直方图波峰
				row_num, col_num= gray_img.shape[:2]
				#去掉车牌上下边缘1个像素,避免白边影响阈值判断
				gray_img = gray_img[1:row_num-1]
				# cv2.imshow("gray_img", gray_img)#二值化
				# cv2.waitKey(0)
				y_histogram = np.sum(gray_img, axis=0)
				y_min = np.min(y_histogram)
				y_average = np.sum(y_histogram)/y_histogram.shape[0]
				y_threshold = (y_min + y_average)/5#U和0要求阈值偏小,否则U和0会被分成两半

				wave_peaks = find_waves(y_threshold, y_histogram)

		
				#车牌字符数应大于6
				if len(wave_peaks) <= 6:
					print("peak less 1:", len(wave_peaks))
					continue

				wave = max(wave_peaks, key=lambda x:x[1]-x[0])
				max_wave_dis = wave[1] - wave[0]
				#判断是否是左侧车牌边缘
				if wave_peaks[0][1] - wave_peaks[0][0] < max_wave_dis/3 and wave_peaks[0][0] == 0:
					wave_peaks.pop(0)

				#组合分离汉字
				cur_dis = 0
				for i,wave in enumerate(wave_peaks):
					if wave[1] - wave[0] + cur_dis > max_wave_dis * 0.6:
						break
					else:
						cur_dis += wave[1] - wave[0]
				if i > 0:
					wave = (wave_peaks[0][0], wave_peaks[i][1])
					wave_peaks = wave_peaks[i+1:]
					wave_peaks.insert(0, wave)

				#去除车牌上的分隔点
				point = wave_peaks[2]
				if point[1] - point[0] < max_wave_dis/3:
					point_img = gray_img[:,point[0]:point[1]]
					if np.mean(point_img) < 255/5:
						wave_peaks.pop(2)

				if len(wave_peaks) <= 6:
					print("peak less 2:", len(wave_peaks))
					continue
				part_cards = seperate_card(gray_img, wave_peaks)
				for i, part_card in enumerate(part_cards):
					#可能是固定车牌的铆钉
					if np.mean(part_card) < 255/5:
						print("a point")
						continue
					part_card_old = part_card
	
					w = part_card.shape[1] // 3
					part_card = cv2.copyMakeBorder(part_card, 0, 0, w, w, cv2.BORDER_CONSTANT, value = [0,0,0])
					part_card = cv2.resize(part_card, (SZ, SZ), interpolation=cv2.INTER_AREA)
		
					cv2.destroyAllWindows()
	
					part_card = train.preprocess_hog([part_card])#preprocess_hog([part_card])
					if i == 0:
						resp = self.modelchinese.predict(part_card)#第一个字符调用中文svm模型
						charactor = train.provinces[int(resp[0]) - PROVINCE_START]
					else:
						resp = self.model.predict(part_card)#其他字符调用字母数字svm模型
						charactor = chr(resp[0])
					#判断最后一个数是否是车牌边缘,假设车牌边缘被认为是1
					if charactor == "1" and i == len(part_cards)-1:
						if part_card_old.shape[0]/part_card_old.shape[1] >= 8:#1太细,认为是边缘
							print(part_card_old.shape)
							continue
					predict_result.append(charactor)
				roi = card_img
				card_color = color
				break

		return predict_result, roi, card_color#识别到的字符、定位的车牌图像、车牌颜色

if __name__ == '__main__':
	c = CardPredictor()
	c.load_svm()#加载训练好的模型
	img  = cv2.imread("test\\car20.jpg")
	img = cv2.resize(img, (1000, 1000), interpolation=cv2.INTER_AREA)
	r, roi, color = c.predict(img)
	print(r)

运行结果:

车牌颜色: blue
['津', 'N', 'A', 'V', '8', '8', '8']

从结果看比上一节的准确多了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/921601.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

无涯教程-PHP - preg_replace()函数

preg_replace() - 语法 mixed preg_replace (mixed pattern, mixed replacement, mixed string [, int limit [, int &$count]] ); preg_replace()函数的操作与POSIX函数ereg_replace()相同&#xff0c;不同之处在于可以在模式和替换输入参数中使用正则表达式。 可选的输…

PowerJob的启动及使用

首先&#xff0c;本文中提到的server就是指powerjob-server模块&#xff08;也就是powerJob的重点之一的调度服务&#xff09; 一、初始化项目 1. PowerJob的下载 官方文档 2. 导入到IDEA中&#xff0c;下载依赖后&#xff0c;打开powerjob-server模块的a…

开发中常用的小脚本、工具

文章目录 1. mysql数据库相关1.1 查看数据库各表占用内存大小1.2 数据库字段脱敏脚本 1. mysql数据库相关 1.1 查看数据库各表占用内存大小 SELECT table_name, ROUND(((data_length index_length) / 1024 / 1024), 2) AS "Size (MB)" FROM information_schema.t…

Instagram合规运营的10条策略

Instagram每月活跃用户15亿&#xff0c;是跨境外贸开发客户与广告引流的常用工具。本文总结10条Instagram运营基本策略与原则&#xff0c;帮助各位跨境人更好的了解平台规则&#xff0c;规避风险&#xff0c;提高投放效率&#xff01; 1、使用商业账号 企业在instagram 上进行…

高精度参考电压源是什么意思

高精度参考电压源是一种能够提供稳定、准确且可靠的参考电压的电路或器件。在电子系统中&#xff0c;参考电压起着至关重要的作用&#xff0c;它被用作比较、校准、测量等各种应用中的基准电压。高精度参考电压源能够提供高精度的参考电压&#xff0c;具有很低的温漂、噪声和漂…

软考A计划-系统集成项目管理工程师-项目变更管理

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例点击跳转>软考全系列点击跳转>蓝桥系列 &#x1f449;关于作者 专注于Android/Unity和各种游…

2023年天府杯A 题:震源属性识别模型构建与震级预测

基于数据分析的震源属性识别模型构建与震级预测问题的研究 问题一&#xff1a; 解题思路: 第一部: 对数据进行一个处理&#xff0c;将数据进行分类&#xff0c;求出数据中的最大值&#xff0c;最小值&#xff0c;极差&#xff0c;方差等等一系列特征数据。&#xff0c;将天然…

Git企业开发控制理论和实操-从入门到深入(三)|分支管理

前言 那么这里博主先安利一些干货满满的专栏了&#xff01; 首先是博主的高质量博客的汇总&#xff0c;这个专栏里面的博客&#xff0c;都是博主最最用心写的一部分&#xff0c;干货满满&#xff0c;希望对大家有帮助。 高质量博客汇总 然后就是博主最近最花时间的一个专栏…

PhantomJS+java 后端生成echart图表的图片

PhantomJSjava 后端生成echart图表的图片 前言源码效果实现echarts-convertPhantomJS实现echarts截图得到图片java延时读取base64数据 参考 前言 该项目仅用作个人学习使用 源码 地址 docker镜像&#xff1a; registry.cn-chengdu.aliyuncs.com/qinjie/java-phantomjs:1.0 …

【Git】代码误推送还原(真实项目环境,非纸上谈兵)

背景 RT&#xff0c; 我今天眼睛花了&#xff0c;不小心把工作分支【合并】到了一个不相干的功能分支上&#xff0c;并且代码已经推送到远程仓库了。于是&#xff0c;只能尝试还原到上一次提交中。 【合并】分支有一个点我们是不可避免的&#xff0c;文字很难描述&#xff0c;…

一文总结:如何在csdn中使用markdown写出精美文章

这里写自定义目录标题 欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题&#xff0c;有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants 创建一个自定义列表如何创建一个…

导出功能exportExcel (现成直接用)

1. 实体类字段上加 Excel(name "xxx"), 表示要导出的字段 Excel(name "订单号")private String orderNo; 2. controller (get请求) /*** 导出订单列表*/ApiOperation("导出订单列表")GetMapping("/export")public void export(HttpS…

Ompl初探

在/ompl-1.x.0/build/Release/bin下有很多生成的demo可执行文件 在终端执行 ./demo_Point2DPlanning 测试程序 #include <ompl/base/SpaceInformation.h> #include <ompl/base/spaces/SE3StateSpace.h> #include <ompl/base/StateSpace.h> #include <o…

Python“牵手”蘑菇街商品详情API接口运用场景及功能介绍,蘑菇街接口申请指南

蘑菇街是专注于时尚女性消费者的电子商务网站&#xff0c;是时尚和生活方式目的地。 蘑菇街通过形式多样的时尚内容等时尚商品&#xff0c;让人们在分享和发现流行趋势的同时&#xff0c;享受购物体验。蘑菇街不是一个购物平台&#xff0c;它是一个购物指南网站&#xff0c;帮…

python3对接godaddy API,实现自动更改域名解析(DDNS)

python3对接godaddy API&#xff0c;实现自动更改域名解析&#xff08;DDNS&#xff09; 文章开始前&#xff0c;先解释下如下问题&#xff1a; ①什么是域名解析&#xff1f; 域名解析一般是指通过一个域名指向IP地址&#xff08;A解析&#xff09;&#xff0c;然后我们访问…

缓存之争:Redis和JVM面对面,你会选谁?

大家好&#xff0c;我是你们的小米&#xff01;今天要和大家聊聊一个在技术面试中经常被问到的问题&#xff1a;Redis缓存和JVM缓存有什么区别呢&#xff1f;相信这个问题在不少小伙伴的面试路上都遇到过&#xff0c;今天就让我们来深入剖析一下吧&#xff01; 缓存的作用和意…

【Spring Boot】详解条件注解以及条件拓展注解@Conditional与@ConditionalOnXxx

Spring Conditional Spring 4.0提供的注解。作用是给需要装载的Bean增加一个条件判断。只有满足条件才会装在到IoC容器中。而这个条件可以由自己去完成的&#xff0c;可以通过重写Condition接口重写matches()方法去实现自定义的逻辑。所以说这个注解增加了对Bean装载的灵活性。…

基于FPGA视频接口之HDMI2.0编/解码

简介 为什么要特别说明HDMI的版本,是因为HDMI的版本众多,代表的HDMI速度同样不同,当前版本在HDMI2.1速度达到48Gbps,可以传输4K及以上图像,但我们当前还停留在1080P@60部分,且使用的芯片和硬件结构有很大差别,故将HDMI分为两个部分说明1080@60以下分辨率和4K以上分辨率(…

怎么写出更好的高质量内容输出

为了更好地输出高质量的内容&#xff0c;不仅仅需要了解写作的基本原则&#xff0c;还需要深入挖掘目标读者的需求、持续的自我提升以及对信息的严格筛选。以下是一些建议&#xff0c;帮助你更好地输出高质量的内容&#xff1a; 1.充分了解你的受众 调查和了解你的目标读者&am…

SpringBoot整合阿里云OSS,实现图片上传

在项目中&#xff0c;将图片等文件资源上传到阿里云的OSS&#xff0c;减少服务器压力。 项目中导入阿里云的SDK <dependency><groupId>com.aliyun.oss</groupId><artifactId>aliyun-sdk-oss</artifactId><version>3.10.2</version>…