又是基本没用上系列
第一章 1、
要计算一张100x100的彩色图像(假设是24位彩色,即每个像素用3个字节表示)的文件大小,可以按照以下步骤进行:
计算像素总数:100像素 × 100像素 = 10,000像素。
计算每个像素的字节数:24位彩色图像,每个像素用3个字节表示。
计算总字节数:10,000像素 × 3字节/像素 = 30,000字节。
将字节转换为KB:30,000字节 ÷ 1,024字节/KB ≈ 29.29KB。
因此,一张100x100的24位彩色图像,不经过压缩,文件大小大约是30KB。
选项B(30KB)是正确的。
2、 3、 4、 长6个cell高4个cell,bin=5,一个cell出5个数,一个block出4 × 5=20个数,一共有(6-1) × (4-1)=5 × 3=15个block,所以一共15 × 20=300
代码: 1、饱和度对比度亮度,重点是对比度 1 2 3 4 5 6 7 8 9 10 mean = np.mean(saturation_img) alpha = self .contrast_slider.value() / 100.0 beta = self .brightness_slider.value() contrast_img = (saturation_img - mean) * alpha + mean + beta contrast_img = np.clip(contrast_img, 0 , 255 ).astype(np.uint8) brightness_img = cv2.convertScaleAbs(contrast_img, alpha=1 , beta=self .brightness_slider.value())
完整代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 import sysimport cv2import numpy as npfrom PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton, QVBoxLayout, QHBoxLayout, QLabel, QFileDialog, QSlider, QWidget,QMessageBoxfrom PyQt5.QtCore import Qtfrom PyQt5.QtGui import QImage, QPixmapfrom PyQt5 import QtWidgetsclass MainWindow (QMainWindow ): def __init__ (self ): super ().__init__() self .setWindowTitle("Saturation and Contrast Adjustment" ) screen = QApplication.primaryScreen() screen_geometry = screen.geometry() window_width, window_height = 800 , 600 window_geometry = self .frameGeometry() center_point = screen_geometry.center() window_geometry.moveCenter(center_point) self .setGeometry(window_geometry.x(), window_geometry.y(), window_width, window_height) self .init_ui() def init_ui (self ): central_widget = QWidget(self ) layout = QVBoxLayout(central_widget) topLayout = QtWidgets.QVBoxLayout() saturation_layout = QVBoxLayout() self .saturation_slider = QSlider(Qt.Horizontal, self ) self .saturation_slider.setMinimum(0 ) self .saturation_slider.setMaximum(200 ) self .saturation_slider.setValue(100 ) self .saturation_slider.valueChanged[int ].connect(self .update_saturation) self .saturation_label = QLabel("Saturation: 100%" , self ) self .saturation_label.setAlignment(Qt.AlignCenter) self .saturation_slider.hide() self .saturation_label.hide() saturation_layout.addWidget(self .saturation_slider) saturation_layout.addWidget(self .saturation_label) topLayout.addLayout(saturation_layout) contrast_layout = QVBoxLayout() self .contrast_slider = QSlider(Qt.Horizontal, self ) self .contrast_slider.setMinimum(0 ) self .contrast_slider.setMaximum(200 ) self .contrast_slider.setValue(100 ) self .contrast_slider.valueChanged[int ].connect(self .update_contrast) self .contrast_label = QLabel("Contrast: 100%" , self ) self .contrast_label.setAlignment(Qt.AlignCenter) self .contrast_slider.hide() self .contrast_label.hide() contrast_layout.addWidget(self .contrast_slider) contrast_layout.addWidget(self .contrast_label) topLayout.addLayout(contrast_layout) brightness_layout = QVBoxLayout() self .brightness_slider = QSlider(Qt.Horizontal, self ) self .brightness_slider.setMinimum(-100 ) self .brightness_slider.setMaximum(100 ) self .brightness_slider.setValue(0 ) self .brightness_slider.valueChanged[int ].connect(self .update_brightness) self .brightness_label = QLabel("Brightness: 0%" , self ) self .brightness_label.setAlignment(Qt.AlignCenter) self .brightness_slider.hide() self .brightness_label.hide() brightness_layout.addWidget(self .brightness_slider) brightness_layout.addWidget(self .brightness_label) topLayout.addLayout(brightness_layout) layout.addLayout(topLayout) lowLayout = QtWidgets.QHBoxLayout() original_layout = QVBoxLayout() self .text = QLabel("饱和度、对比度、亮度调整" ) self .text.setAlignment(Qt.AlignCenter) original_layout.addWidget(self .text) self .button = QPushButton('请选择图片文件' , self ) self .button.setFixedSize(250 ,30 ) self .button.clicked.connect(self .load_image) original_layout.addWidget(self .button,alignment=Qt.AlignCenter) self .text_ori = QLabel("原图" ,self ) self .text_ori.setAlignment(Qt.AlignCenter) self .text_ori.hide() original_layout.addWidget(self .text_ori) self .ori_image_label = QLabel(self ) self .ori_image_label.setAlignment(Qt.AlignCenter) self .ori_image_label.hide() original_layout.addWidget(self .ori_image_label) lowLayout.addLayout(original_layout) changed_layout = QVBoxLayout() self .button_download = QPushButton('保存变换之后的图片' , self ) self .button_download.setFixedSize(250 ,30 ) self .button_download.clicked.connect(self .download_image) self .button_download.hide() changed_layout.addWidget(self .button_download,alignment=Qt.AlignCenter) self .text_chan = QLabel("变换图" ,self ) self .text_chan.setAlignment(Qt.AlignCenter) self .text_chan.hide() changed_layout.addWidget(self .text_chan) self .changed_image_label = QLabel(self ) self .changed_image_label.setAlignment(Qt.AlignCenter) self .changed_image_label.hide() changed_layout.addWidget(self .changed_image_label) lowLayout.addLayout(changed_layout) layout.addLayout(lowLayout) self .setCentralWidget(central_widget) self .image = None self .changed_image=None def load_image (self ): options = QFileDialog.Options() file_name, _ = QFileDialog.getOpenFileName(self , "Open Image" , "" , "Image Files (*.png *.jpg *.bmp)" , options=options) if file_name: self .image = cv2.imread(file_name) if self .image is None : QMessageBox.warning(self , "Warning" , "图片打开失败,文件名或路径包含中文,不可识别,请将文件放置在英文路径下" ) return self .image = cv2.resize(self .image, (400 ,400 )) self .saturation_slider.setValue(100 ) self .contrast_slider.setValue(100 ) self .brightness_slider.setValue(0 ) self .update_image() self .text.hide() self .saturation_label.show() self .saturation_slider.show() self .contrast_label.show() self .contrast_slider.show() self .brightness_label.show() self .brightness_slider.show() self .text_ori.show() self .ori_image_label.show() self .text_chan.show() self .button_download.show() self .changed_image_label.show() else : QMessageBox.warning(self , "Warning" , "图片上传失败" ) def update_image (self ): if self .image is not None : hsv_img = cv2.cvtColor(self .image, cv2.COLOR_BGR2HSV) hsv_img[..., 1 ] = hsv_img[..., 1 ] * (self .saturation_slider.value() / 100.0 ) saturation_img = cv2.cvtColor(hsv_img, cv2.COLOR_HSV2BGR) mean = np.mean(saturation_img) alpha = self .contrast_slider.value() / 100.0 beta = self .brightness_slider.value() contrast_img = (saturation_img - mean) * alpha + mean + beta contrast_img = np.clip(contrast_img, 0 , 255 ).astype(np.uint8) brightness_img = cv2.convertScaleAbs(contrast_img, alpha=1 , beta=self .brightness_slider.value()) self .changed_image = brightness_img height, width, channel = brightness_img.shape bytes_per_line = 3 * width q_image = QImage(brightness_img.data, width, height, bytes_per_line, QImage.Format_BGR888) pixmap = QPixmap.fromImage(q_image) self .changed_image_label.setPixmap(pixmap) height, width, channel = self .image.shape bytes_per_line = 3 * width q_image = QImage(self .image.data, width, height, bytes_per_line, QImage.Format_BGR888) pixmap = QPixmap.fromImage(q_image) self .ori_image_label.setPixmap(pixmap) else : QMessageBox.warning(self , "Warning" , "请先上传图片" ) def update_saturation (self, value ): self .saturation_label.setText(f"Saturation: {value} %" ) self .update_image() def update_contrast (self, value ): self .contrast_label.setText(f"Contrast: {value} %" ) self .update_image() def update_brightness (self, value ): self .brightness_label.setText(f"Brightness: {value} %" ) self .update_image() def download_image (self ): if self .image is not None : options = QFileDialog.Options() file_name, _ = QFileDialog.getSaveFileName(self , "Save Image" , "changed.jpg" , "Image Files (*.png *.jpg *.bmp)" , options=options) if file_name: cv2.imwrite(file_name, self .changed_image) QMessageBox.information(self , "Success" , "图片保存成功" ) if __name__ == '__main__' : app = QApplication(sys.argv) main_window = MainWindow() main_window.show() sys.exit(app.exec_())
2、hog特征 2、1手动实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 import numpy as npimport cv2from scipy import signalimport mathfrom matplotlib import pyplot as pltfrom skimage import data, exposureclass HOG (): def __init__ (self,img,cell_size=16 ,bin_size=8 ): self .img = img self .img = cv2.resize(self .img,(224 ,224 )) self .img = np.power(self .img/float (np.max (self .img)),1.5 ) self .cell_size = cell_size self .bin_size = bin_size self .angle_range = 360 /self .bin_size def grad_and_theta (self ): kernel_x = np.array([[-1 ,0 ,1 ]]) dx = signal.convolve2d(self .img,kernel_x,boundary='symm' ,mode='same' ) kernel_y = np.array([[-1 ,0 ,1 ]]).T dy = signal.convolve2d(self .img,kernel_y,boundary='symm' ,mode='same' ) grad = np.sqrt(dx**2 +dy**2 ) theta = np.degrees(np.arctan2(dx,dy)) theta[theta<0 ] = np.pi+theta[theta<0 ] return grad,theta def cell_hist (self,grad,theta ): cell_hist = self .bin_size*[0 ] for i in range (grad.shape[0 ]): for j in range (grad.shape[1 ]): index = int (theta[i][j]/self .angle_range) rest = theta[i][j]%self .angle_range if rest==0 : cell_hist[index] += grad[i][j] else : cell_hist[index] += grad[i][j]*(1 -rest/self .angle_range) cell_hist[(index+1 )%self .bin_size] += grad[i][j]*(rest/self .angle_range) return cell_hist def block_hist (self,grad,theta ): height,width = self .img.shape cell_grad_vec = np.zeros((int (height/self .cell_size),int (width/self .cell_size),self .bin_size)) for i in range (cell_grad_vec.shape[0 ]): for j in range (cell_grad_vec.shape[1 ]): cell_grad_t = grad[i*self .cell_size:(i+1 )*self .cell_size,j*self .cell_size:(j+1 )*self .cell_size] cell_theta_t = theta[i*self .cell_size:(i+1 )*self .cell_size,j*self .cell_size:(j+1 )*self .cell_size] cell_grad_vec[i][j] = self .cell_hist(cell_grad_t,cell_theta_t) hog_image = self .render_gradient(np.zeros(self .img.shape),cell_grad_vec) return hog_image def render_gradient (self, image, cell_gradient ): cell_width = self .cell_size / 2 max_mag = np.array(cell_gradient).max () for x in range (cell_gradient.shape[0 ]): for y in range (cell_gradient.shape[1 ]): cell_grad = cell_gradient[x][y] cell_grad /= max_mag angle = 0 angle_gap = self .angle_range for magnitude in cell_grad: angle_radian = math.radians(angle) x1 = int (x * self .cell_size + magnitude * cell_width * math.cos(angle_radian)) y1 = int (y * self .cell_size + magnitude * cell_width * math.sin(angle_radian)) x2 = int (x * self .cell_size - magnitude * cell_width * math.cos(angle_radian)) y2 = int (y * self .cell_size - magnitude * cell_width * math.sin(angle_radian)) cv2.line(image, (y1, x1), (y2, x2), int (255 * math.sqrt(magnitude))) angle += angle_gap return image if __name__=='__main__' : img = cv2.imread("pic/sky1.jpg" ,0 ) hog = HOG(img,16 ,8 ) grad, theta = hog.grad_and_theta() print (grad.shape[0 ],theta.shape) image = hog.block_hist(grad, theta) fig, (ax1, ax2) = plt.subplots(1 , 2 , figsize=(10 , 6 ), sharex=True , sharey=True ) ax1.axis('off' ) ax1.imshow(img, cmap=plt.cm.gray) ax1.set_title('Input image' ) hog_image_rescaled = exposure.rescale_intensity(image, in_range=(0 , 10 )) ax2.axis('off' ) ax2.imshow(hog_image_rescaled, cmap=plt.cm.gray) ax2.set_title('Histogram of Oriented Gradients' ) plt.show()
2、2库函数 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 import cv2import numpy as npimport matplotlib.pyplot as pltfrom skimage.feature import hogfrom skimage import data, exposureimage = cv2.imread('pic/sky1.jpg' , 0 ) image = cv2.resize(image, (224 , 224 )) image = np.float32(image) / 255.0 fd, hog_image = hog(image, orientations=8 , pixels_per_cell=(16 , 16 ), cells_per_block=(1 , 1 ), visualize=True , ) fig, (ax1, ax2) = plt.subplots(1 , 2 , figsize=(10 , 6 ), sharex=True , sharey=True ) ax1.axis('off' ) ax1.imshow(image, cmap=plt.cm.gray) ax1.set_title('Input image' ) hog_image_rescaled = exposure.rescale_intensity(hog_image, in_range=(0 , 10 )) ax2.axis('off' ) ax2.imshow(hog_image_rescaled, cmap=plt.cm.gray) ax2.set_title('Histogram of Oriented Gradients' ) plt.show()
2、3 hog+SVM 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 import cv2from skimage.feature import hogimport requestsimport numpy as npimport osimport gzip import certififrom sklearn.svm import SVCfrom sklearn.preprocessing import StandardScalerdef load_mnist_images (filename ): with gzip.open (filename,'rb' ) as f: data = np.frombuffer(f.read(),np.uint8,offset=16 ) return data.reshape(-1 ,28 ,28 ) def load_mnist_labels (filename ): with gzip.open (filename,'rb' ) as f: data = np.frombuffer(f.read(),np.uint8,offset=8 ) return data def HOG (images ): hog = cv2.HOGDescriptor((28 ,28 ),(4 ,4 ),(4 ,4 ),(4 ,4 ),9 ) hog_image=[] for image in images: feature = hog.compute(image) hog_image.append(feature.flatten()) return np.array(hog_image) def svm_model (): model = cv2.ml.SVM_create() model.setGamma(0.1 ) model.setC(10 ) model.setKernel(cv2.ml.SVM_RBF) model.setType(cv2.ml.SVM_C_SVC) return model x_train = load_mnist_images('train-images-idx3-ubyte.gz' ) y_train = load_mnist_labels('train-labels-idx1-ubyte.gz' ) x_test = load_mnist_images('t10k-images-idx3-ubyte.gz' ) y_test = load_mnist_labels('t10k-labels-idx1-ubyte.gz' ) x_train_hog = HOG(x_train) x_test_hog = HOG(x_test) x_train_hog = x_train_hog.astype('float32' ) x_test_hog = x_test_hog.astype('float32' ) y_train = y_train.astype('int32' ) y_test = y_test.astype('int32' ) print ("data ready" )SVM = svm_model() print ("SVM created" )SVM.train(x_train_hog,cv2.ml.ROW_SAMPLE,y_train) print ("SVM trained" )SVM.save('svm_model.xml' ) _,y_pred = SVM.predict(x_test_hog) y_pred = y_pred.flatten().astype('int32' ) print ("prediction done" )acc = np.sum (y_pred==y_test)/len (y_test) print ("Accuracy: " ,acc)
3、直方图相似性匹配 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 import cv2import numpy as npimport osimport matplotlib.pyplot as plt def cal_hist (channel ): hist =[0 for i in range (256 )] w,d=channel.shape for i in range (w): for j in range (d): hist[channel[i][j]]+=1 return hist def image_hist (image ): image = cv2.resize(image,(256 ,256 )) hists=[] b_channel,g_channel,r_channel = cv2.split(image) b_hist = cal_hist(b_channel) g_hist = cal_hist(g_channel) r_hist = cal_hist(r_channel) hists.append(b_hist) hists.append(g_hist) hists.append(r_hist) return hists def cal_simility (hist1,hist2 ): degrees=0 for i in range (3 ): degree = 0 for j in range (256 ): if hist1[i][j]==hist2[i][j]: degree+=1 else : degree+= (1 -(abs (hist1[i][j]-hist2[i][j])/max (hist1[i][j],hist2[i][j]))) degrees += degree /256 degrees/=3 return degrees image1 = cv2.imread("pic/sky3.jpg" ) image1_hist = image_hist(image1) path = "pic" images = [] degrees = [] image_paths = [] for image_name in os.listdir(path): pic_path = os.path.join(path, image_name) image = cv2.imread(pic_path) image = cv2.resize(image,(256 ,256 )) image_hist_ = image_hist(image) degree = cal_simility(image1_hist, image_hist_) images.append(image) degrees.append(degree) image_paths.append(pic_path) sorted_indices = np.argsort(degrees)[::-1 ] sorted_images = [images[i] for i in sorted_indices] sorted_degrees = [degrees[i] for i in sorted_indices] sorted_image_paths = [image_paths[i] for i in sorted_indices] plt.figure(figsize=(15 , 10 )) num_images = len (sorted_images) rows = int (np.ceil(num_images / 3 )) for i in range (num_images): plt.subplot(rows, 3 , i + 1 ) plt.imshow(cv2.cvtColor(sorted_images[i], cv2.COLOR_BGR2RGB)) plt.title(f"{os.path.basename(sorted_image_paths[i])} \nSimilarity: {sorted_degrees[i]:.2 f} " ) plt.axis('off' ) plt.tight_layout() plt.show()
第二章 三层全连接推导
代码实现:GTP4o version 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 import numpy as npw1, w2, w3, w4 = 0.15 , 0.20 , 0.25 , 0.30 w5, w6, w7, w8 = 0.40 , 0.45 , 0.50 , 0.55 b1, b2 = 0.35 , 0.60 x = np.array([0.05 , 0.10 ]) y_true = np.array([0.01 , 0.99 ]) def sigmoid (z ): return 1 / (1 + np.exp(-z)) def sigmoid_derivative (z ): return sigmoid(z) * (1 - sigmoid(z)) def forward_propagation (x, w, b ): z1 = x[0 ] * w[0 ] + x[1 ] * w[1 ] + b[0 ] z2 = x[0 ] * w[2 ] + x[1 ] * w[3 ] + b[0 ] h1 = sigmoid(z1) h2 = sigmoid(z2) z3 = h1 * w[4 ] + h2 * w[5 ] + b[1 ] z4 = h1 * w[6 ] + h2 * w[7 ] + b[1 ] o1 = sigmoid(z3) o2 = sigmoid(z4) return np.array([h1, h2]), np.array([o1, o2]), np.array([z1, z2, z3, z4]) def backpropagation (x, y_true, hidden_output, output, intermediate_z, w, b, lr ): delta_o1 = (output[0 ] - y_true[0 ]) * sigmoid_derivative(intermediate_z[2 ]) delta_o2 = (output[1 ] - y_true[1 ]) * sigmoid_derivative(intermediate_z[3 ]) delta_h1 = (delta_o1 * w[4 ] + delta_o2 * w[6 ]) * sigmoid_derivative(intermediate_z[0 ]) delta_h2 = (delta_o1 * w[5 ] + delta_o2 * w[7 ]) * sigmoid_derivative(intermediate_z[1 ]) w[4 ] -= lr * delta_o1 * hidden_output[0 ] w[5 ] -= lr * delta_o1 * hidden_output[1 ] w[6 ] -= lr * delta_o2 * hidden_output[0 ] w[7 ] -= lr * delta_o2 * hidden_output[1 ] w[0 ] -= lr * delta_h1 * x[0 ] w[1 ] -= lr * delta_h1 * x[1 ] w[2 ] -= lr * delta_h2 * x[0 ] w[3 ] -= lr * delta_h2 * x[1 ] b[1 ] -= lr * (delta_o1 + delta_o2) b[0 ] -= lr * (delta_h1 + delta_h2) return w, b w = np.array([w1, w2, w3, w4, w5, w6, w7, w8]) b = np.array([b1, b2]) lr = 0.5 for epoch in range (10000 ): hidden_output, output, intermediate_z = forward_propagation(x, w, b) loss = 0.5 * ((y_true[0 ] - output[0 ])**2 + (y_true[1 ] - output[1 ])**2 ) if epoch % 1000 == 0 : print (f"Epoch {epoch} , Loss: {loss:.6 f} " ) w, b = backpropagation(x, y_true, hidden_output, output, intermediate_z, w, b, lr) hidden_output, output, _ = forward_propagation(x, w, b) print ("训练完成后:" )print ("隐藏层输出: h1 = {:.4f}, h2 = {:.4f}" .format (hidden_output[0 ], hidden_output[1 ]))print ("输出层输出: o1 = {:.4f}, o2 = {:.4f}" .format (output[0 ], output[1 ]))
第三章 卷积计算公式:
输出尺寸:(32+2 x 2-5)/1+1=32+4-5+1=32
参数量:10个5x5卷积核,维度为3,10x5x5x3=750,还有10个偏置,共760个参数
第四章 转置卷积公式:
答案错了
RCNN (Region-based Convolutional Neural Networks)
选择候选区域 :使用选择性搜索(Selective Search)算法生成大约 2000 个候选区域(Region Proposals)。
特征提取 :将每个候选区域调整为固定大小,并使用卷积神经网络(CNN)提取特征。
分类和回归 :使用支持向量机(SVM)对每个候选区域进行分类,并使用线性回归调整边界框。
缺点 :
计算量大,速度慢,因为每个候选区域都需要单独通过 CNN 进行特征提取。
存储需求高,因为需要存储每个候选区域的特征。
Fast RCNN
共享特征提取 :整个图像通过 CNN 进行一次特征提取,生成特征图。
候选区域生成 :在特征图上使用选择性搜索生成候选区域。
ROI Pooling :将候选区域映射到特征图上,并使用 ROI Pooling 层将不同大小的候选区域调整为相同大小。
分类和回归 :使用全连接层对每个候选区域进行分类和边界框回归。
改进 :
通过共享特征提取,大大减少了计算量,提高了速度。
使用 ROI Pooling 层,使得不同大小的候选区域可以在同一个特征图上进行处理。
Faster RCNN
共享特征提取 :整个图像通过 CNN 进行一次特征提取,生成特征图。
区域建议网络(RPN) :在特征图上使用 RPN 生成候选区域。RPN 是一个轻量级网络,可以直接在特征图上生成候选区域。
ROI Pooling :将 RPN 生成的候选区域映射到特征图上,并使用 ROI Pooling 层将不同大小的候选区域调整为相同大小。
分类和回归 :使用全连接层对每个候选区域进行分类和边界框回归。
改进 :
引入 RPN 代替选择性搜索,进一步提高了候选区域生成的速度和质量。
RPN 和 Fast RCNN 共享特征提取网络,使得整个网络可以端到端训练,提高了检测精度和速度。
总结
RCNN :使用选择性搜索生成候选区域,每个候选区域单独通过 CNN 提取特征,速度慢。
Fast RCNN :共享特征提取,使用 ROI Pooling 层处理候选区域,提高了速度。
Faster RCNN :引入 RPN 生成候选区域,进一步提高了速度和精度,实现了端到端训练。
第五章 CBIR: 大规模图像集的基于内容的图像检索(Content-Based Image Retrieval,简称 CBIR)是一种利用图像的视觉内容(如颜色、纹理、形状等)进行图像检索的方法。与基于文本的图像检索不同,CBIR 不依赖于图像的元数据(如标签、描述),而是直接分析图像的内容来进行检索。
CBIR 的基本原理
特征提取 :从图像中提取视觉特征,如颜色直方图、纹理特征、形状特征等。这些特征通常以向量的形式表示。
特征索引 :将提取的特征存储在数据库中,并建立索引,以便快速检索。
相似性度量 :定义一种度量图像特征相似性的算法,如欧氏距离、余弦相似度等。
检索过程
用户提供查询图像。
从查询图像中提取特征。
计算查询图像特征与数据库中图像特征之间的相似性。
返回与查询图像最相似的图像。
向量检索 向量检索(Vector Retrieval)是一种基于向量空间模型的检索方法,用于在高维向量空间中查找与查询向量相似的向量。向量检索广泛应用于信息检索、推荐系统、图像检索、自然语言处理等领域。
向量检索是一种基于向量空间模型的检索方法,通过将数据转换为向量表示,并使用相似性度量和高效的索引结构,快速查找与查询向量相似的向量。向量检索在信息检索、推荐系统、图像检索等领域有广泛的应用。
向量检索的基本原理
特征表示 :将数据(如文本、图像、音频等)转换为向量表示。例如,文本可以通过词嵌入(如 Word2Vec、GloVe、BERT)转换为向量,图像可以通过卷积神经网络(CNN)提取特征向量。
相似性度量 :定义一种度量向量之间相似性的方法。常用的相似性度量包括欧氏距离、余弦相似度、曼哈顿距离等。
索引结构 :构建高效的索引结构,以便快速检索相似向量。常用的索引结构包括 KD 树、球树(Ball Tree)、局部敏感哈希(LSH)、近似最近邻(ANN)等。
检索过程
用户提供查询向量。
计算查询向量与数据库中向量的相似性。
返回与查询向量最相似的向量。
向量检索的应用场景
信息检索 :在文档库中查找与查询文本相似的文档。
推荐系统 :根据用户的历史行为向量,推荐相似的物品。
图像检索 :在图像库中查找与查询图像相似的图像。
自然语言处理 :在语料库中查找与查询句子相似的句子。
音频检索 :在音频库中查找与查询音频相似的音频。
向量数据库 向量数据库(Vector Database)是一种专门用于存储、索引和检索高维向量数据的数据库系统。随着机器学习和深度学习的发展,向量数据库在处理和管理大规模向量数据方面变得越来越重要。向量数据库通常用于支持基于内容的检索、推荐系统、图像和文本搜索等应用。
向量数据库是一种专门用于存储、索引和检索高维向量数据的数据库系统,广泛应用于图像检索、文本检索、推荐系统等领域。通过使用高效的索引结构和相似性搜索算法,向量数据库能够在大规模数据中快速查找与查询向量相似的向量。
向量数据库的特点
高维数据存储 :能够高效地存储和管理高维向量数据。
相似性搜索 :支持快速的相似性搜索,通常使用近似最近邻(Approximate Nearest Neighbor, ANN)算法。
高效索引 :使用高效的索引结构(如 KD 树、球树、LSH 等)来加速向量检索。
扩展性 :能够处理大规模数据,支持分布式存储和计算。
实时性 :支持实时数据插入、更新和删除操作。
向量数据库的应用场景
图像检索 :在大规模图像库中查找与查询图像相似的图像。
文本检索 :在文档库中查找与查询文本相似的文档。
推荐系统 :根据用户的历史行为向量,推荐相似的物品。
音频检索 :在音频库中查找与查询音频相似的音频。
生物信息学 :在基因序列库中查找相似的基因序列。
常见的向量数据库
Faiss :由 Facebook AI Research 开发的高效相似性搜索库,支持大规模向量数据的快速检索。
Annoy :由 Spotify 开发的近似最近邻搜索库,适用于内存中的大规模数据。
Milvus :一个开源的向量数据库,支持大规模向量数据的存储和检索,具有高扩展性和高性能。
Elasticsearch with k-NN plugin :Elasticsearch 是一个分布式搜索引擎,k-NN 插件支持向量相似性搜索。
第六章 权值:标量(浮点数),本意是体现相关性,或者说依赖关系,一般通过 两个向量点乘得到(但不是直接点乘(相似性),而是乘以一个转换矩阵 后,而且转换后的维度可能发生变化,Why?) 这些转换矩阵的作用是将输入向量映射到不同的空间,以便更好地捕捉和表示相关性。
捕捉不同的特征 :通过使用不同的权重矩阵 (W_Q)、(W_K) 和 (W_V),可以将输入向量映射到不同的特征空间,从而捕捉输入序列中不同的特征和关系。这使得模型能够更好地理解和表示输入数据的复杂性。
提高模型的表达能力 :线性变换可以增加模型的表达能力,使其能够学习到更复杂的模式和关系。不同的线性变换可以捕捉到输入数据的不同方面,从而提高模型的性能。
维度变化 :通过线性变换,可以改变输入向量的维度,以适应不同层的需求。例如,在多头注意力机制中,每个头的维度通常较小,通过线性变换可以将输入向量分割成多个头,每个头独立计算注意力。
自注意力 ●加权求和得到最终结果,但加 的是Value(同样需要转换矩 阵将输入转换成v),为什么 不能直接加输入 a ? 这是因为自注意力机制的设计目的是通过查询向量(Query)和键向量(Key)计算注意力权重,然后使用这些权重对值向量(Value)进行加权求和,从而生成新的表示。这种设计有几个重要的原因:
1. 不同的特征空间 在自注意力机制中,输入向量 (X) 被分别映射到查询向量 (Q)、键向量 (K) 和值向量 (V) 的不同特征空间。这些特征空间的设计目的是为了捕捉输入数据的不同方面:
查询向量 (Q) :用于计算与其他输入向量的相似性。
键向量 (K) :用于计算与查询向量的相似性。
值向量 (V) :用于生成最终的输出表示。
通过这种方式,模型可以更灵活地学习和表示输入数据的不同特征。如果直接使用输入向量 (X) 进行加权求和,模型将无法充分利用这些不同的特征空间。
2. 提高模型的表达能力 通过将输入向量 (X) 映射到值向量 (V),模型可以学习到更复杂的特征表示。值向量 (V) 可以包含输入向量 (X) 的不同方面的信息,从而提高模型的表达能力和性能。
3. 保持一致性 在自注意力机制中,查询向量 (Q) 和键向量 (K) 用于计算注意力权重,而值向量 (V) 用于生成最终的输出表示。这种设计保持了一致性,使得注意力权重可以直接应用于值向量 (V),从而生成新的表示。如果直接使用输入向量 (X),将破坏这种一致性。
综合分析 人脸识别 卷积神经网络(CNN):
使用CNN模型(如VGGFace、FaceNet)进行人脸特征提取。通过训练大量人脸图像,模型能够学习到不同人脸的独特特征。
应用示例:在安全监控系统中,实时捕捉视频流中的人脸,并通过CNN进行特征提取和比对,识别出潜在的嫌疑人。
人脸对齐:
在进行人脸识别之前,使用深度学习算法(如Dlib库中的人脸对齐技术)对人脸进行标准化处理,以提高识别精度。
应用示例:在社交媒体平台中,用户上传的照片经过对齐处理后,系统能够更准确地进行自动标记。
生成对抗网络(GAN):
使用GAN生成高质量的人脸图像,增强训练数据集,提升模型的鲁棒性。
应用示例:在面部表情识别中,通过生成多样化的表情图像,提升模型对不同情绪的识别能力。
拍物检索 深度学习图像分类:
使用预训练的深度学习模型(如ResNet、Inception)进行物体识别。通过迁移学习,针对特定商品进行微调。
应用示例:用户拍摄商品,应用程序通过深度学习模型识别商品类别,并提供相关信息和购买链接。
特征匹配与检索:
利用深度学习提取图像特征向量,构建特征数据库,通过相似度计算实现快速检索。
应用示例:在博物馆中,游客拍摄展品,系统通过特征匹配快速提供展品的详细信息。
图像分割:
使用深度学习进行图像分割(如U-Net),提取物体的精确边界,提升识别的准确性。
应用示例:在植物识别应用中,通过分割技术提取植物的特征,帮助用户更准确地识别植物种类。
这些深度学习技术的结合,使得人脸识别和拍物检索的应用更加智能化和高效
1. 人脸识别 应用场景:
安全监控:
在公共场所(如机场、车站)部署摄像头,实时监控人群,识别可疑人员。
结合大数据分析,识别潜在的犯罪行为,提升公共安全。
身份验证:
在手机、电脑等设备上使用人脸识别进行解锁,替代传统密码。
在金融支付场景中,使用人脸识别进行身份验证,提升安全性。
技术实现:
卷积神经网络(CNN):
模型选择:使用VGGFace、FaceNet或ArcFace等预训练模型,进行人脸特征提取。
特征提取:通过CNN提取128维或256维的特征向量,形成每个人脸的独特表示。
人脸对齐:
技术:使用Dlib库中的人脸关键点检测,确保人脸在同一标准姿态下进行识别。
步骤:检测人脸后,进行旋转和缩放,使得眼睛和嘴巴位置一致,减少姿态变化对识别的影响。
生成对抗网络(GAN):
数据增强:使用GAN生成多样化的人脸图像,增加训练数据的多样性,提升模型的泛化能力。
应用:在训练过程中,生成不同表情、光照条件下的人脸图像,提升模型的鲁棒性。
性能优化:
实时处理:
硬件加速:使用GPU或TPU加速模型推理,确保在高帧率下处理视频流。
模型压缩:采用模型剪枝、量化和知识蒸馏等技术,减少模型大小,提高推理速度。
准确性提升:
数据增强:通过旋转、翻转、亮度调整、噪声添加等方式增强训练数据,提升模型的鲁棒性。
迁移学习:在特定领域(如安防)进行微调,提升模型在特定场景下的表现。
系统架构:
前端:摄像头采集视频流,进行人脸检测和识别。
后端:服务器接收视频流,进行特征提取和比对,返回识别结果。
数据库:存储人脸特征向量和用户信息,支持快速检索。
2. 拍物检索 应用场景:
购物应用:
用户拍摄商品,系统识别并提供购买链接、价格比较和用户评价。
结合AR技术,用户可以在现实环境中查看商品信息。
博物馆导览:
用户拍摄展品,系统提供详细信息、历史背景和相关视频。
结合语音识别,用户可以通过语音询问展品信息。
植物识别:
用户拍摄植物,系统识别植物种类并提供养护建议、生态信息。
技术实现:
深度学习图像分类:
模型选择:使用ResNet、Inception或EfficientNet进行物体识别。
训练数据:收集大量商品或展品的图像,进行标注和分类,确保数据的多样性和代表性。
特征匹配与检索:
特征提取:使用深度学习模型提取图像特征向量,构建特征数据库。
相似度计算:使用余弦相似度、欧氏距离或Hamming距离进行特征匹配,快速检索相似物体。
图像分割:
技术:使用U-Net或Mask R-CNN进行物体边界提取,确保物体特征的准确性。
应用:在植物识别中,通过分割提取植物的特征,帮助用户更准确地识别。
性能优化:
快速检索:
索引结构:使用KD树、LSH(局部敏感哈希)或Faiss等加速特征检索。
缓存机制:对常见查询结果进行缓存,提升响应速度,减少重复计算。
准确性提升:
多模态学习:结合图像和文本信息(如商品描述、用户评价)进行联合学习,提升识别准确性。
在线学习:根据用户反馈不断更新模型,提升系统的适应性和准确性。
系统架构:
前端:用户通过手机或平板拍摄图像,上传至服务器。
后端:服务器接收图像,进行特征提取、匹配和检索,返回识别结果和相关信息。
数据库:存储商品、展品或植物的图像特征向量和相关信息,支持快速检索。
总结 通过深度学习技术的综合应用,能够有效提升人脸识别和拍物检索的准确性和效率,满足实际应用中的需求。这种设计不仅考虑了技术实现,还注重了性能优化,确保系统在实际应用中的可行性和可靠性。通过不断迭代和优化,系统能够适应不断变化的环境和用户需求,提供更好的用户体验。
分析题目 1. 深度学习网络结构 卷积神经网络(CNN)
应用示例:
图像分类:使用CNN对手写数字进行识别(如MNIST数据集)。
目标检测:使用YOLO(You Only Look Once)模型进行实时物体检测。
结构分析:
卷积层:通过卷积操作提取局部特征,使用多个卷积核提取不同特征。
池化层:通过最大池化或平均池化降低特征图的维度,减少计算量。
全连接层:将卷积层提取的特征映射到最终的分类结果。
循环神经网络(RNN)
应用示例:
自然语言处理:使用RNN进行文本生成(如生成诗歌或故事)。
时间序列预测:使用RNN预测股票价格变化。
结构分析:
输入层:接收序列数据(如单词、时间序列)。
隐藏层:通过循环连接处理序列信息,保持上下文信息。
输出层:生成预测结果(如下一个单词或时间点的值)。
生成对抗网络(GAN)
应用示例:
图像生成:使用GAN生成高质量的合成图像(如人脸图像)。
数据增强:通过生成新样本来扩充训练数据集。
结构分析:
生成器:生成假图像,试图欺骗判别器。
判别器:判断输入图像是真实的还是生成的。
对抗训练:生成器和判别器相互博弈,提升生成图像的质量。
2. 损失函数设计 交叉熵损失
应用示例:
多类分类问题:在图像分类任务中,使用交叉熵损失来优化模型(如CIFAR-10数据集)。
分析:
定义:衡量预测概率分布与真实标签分布之间的差异。
优点:适用于多类分类问题,能够有效优化模型,尤其在类别不平衡时表现良好。
均方误差(MSE)
应用示例:
回归问题:在房价预测中,使用MSE来评估模型的预测效果。
分析:
定义:计算预测值与真实值之间的平方差的平均值。
优点:简单易用,适合线性回归模型,能够有效反映预测误差。
对比损失(Contrastive Loss)
应用示例:
人脸识别:在训练人脸识别模型时,使用对比损失来优化相似性和差异性。
分析:
定义:通过最小化相似样本之间的距离和最大化不相似样本之间的距离来训练模型。
优点:有效提升模型对相似性和差异性的学习能力,适合于无监督学习场景。
总结 通过对深度学习网络结构和损失函数的分析,可以深入理解模型的设计思路和优化目标。这些例子展示了不同网络结构和损失函数在实际应用中的重要性和适用性,帮助我们更好地选择合适的模型和损失函数以满足特定任务的需求。