使用IBM ART库生成交通信号牌的攻击样本
目标:生成对抗样本,扰动图像,让原本是“停”的信号牌识别为“禁止驶入”:
代码如下(注意,因为我找的cnn原始模型支持的是灰度图像,所以彩色的对抗样本还需要修改代码):
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 221 222 223 | import cv2, os import numpy as np import numpy as np import tensorflow as tf from keras.models import load_model from tensorflow.keras.layers import Dense from tensorflow.keras.utils import to_categorical from art.estimators.classification import TensorFlowV2Classifier from art.attacks.evasion import FastGradientMethod import matplotlib.pyplot as plt from tensorflow.keras.models import load_model from tensorflow.keras.models import Model from tensorflow.keras.layers import Dense from tensorflow.keras.optimizers import Adam from tensorflow.keras.utils import to_categorical from sklearn.model_selection import train_test_split def getCalssName(classNo): if classNo = = 0 : return 'Speed Limit 20 km/h' elif classNo = = 1 : return 'Speed Limit 30 km/h' elif classNo = = 2 : return 'Speed Limit 50 km/h' elif classNo = = 3 : return 'Speed Limit 60 km/h' elif classNo = = 4 : return 'Speed Limit 70 km/h' elif classNo = = 5 : return 'Speed Limit 80 km/h' elif classNo = = 6 : return 'End of Speed Limit 80 km/h' elif classNo = = 7 : return 'Speed Limit 100 km/h' elif classNo = = 8 : return 'Speed Limit 120 km/h' elif classNo = = 9 : return 'No passing' elif classNo = = 10 : return 'No passing for vechiles over 3.5 metric tons' elif classNo = = 11 : return 'Right-of-way at the next intersection' elif classNo = = 12 : return 'Priority road' elif classNo = = 13 : return 'Yield' elif classNo = = 14 : return 'Stop' elif classNo = = 15 : return 'No vechiles' elif classNo = = 16 : return 'Vechiles over 3.5 metric tons prohibited' elif classNo = = 17 : return 'No entry' elif classNo = = 18 : return 'General caution' elif classNo = = 19 : return 'Dangerous curve to the left' elif classNo = = 20 : return 'Dangerous curve to the right' elif classNo = = 21 : return 'Double curve' elif classNo = = 22 : return 'Bumpy road' elif classNo = = 23 : return 'Slippery road' elif classNo = = 24 : return 'Road narrows on the right' elif classNo = = 25 : return 'Road work' elif classNo = = 26 : return 'Traffic signals' elif classNo = = 27 : return 'Pedestrians' elif classNo = = 28 : return 'Children crossing' elif classNo = = 29 : return 'Bicycles crossing' elif classNo = = 30 : return 'Beware of ice/snow' elif classNo = = 31 : return 'Wild animals crossing' elif classNo = = 32 : return 'End of all speed and passing limits' elif classNo = = 33 : return 'Turn right ahead' elif classNo = = 34 : return 'Turn left ahead' elif classNo = = 35 : return 'Ahead only' elif classNo = = 36 : return 'Go straight or right' elif classNo = = 37 : return 'Go straight or left' elif classNo = = 38 : return 'Keep right' elif classNo = = 39 : return 'Keep left' elif classNo = = 40 : return 'Roundabout mandatory' elif classNo = = 41 : return 'End of no passing' elif classNo = = 42 : return 'End of no passing by vechiles over 3.5 metric tons' def grayscale(img): img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) return img def equalize(img): img = cv2.equalizeHist(img) return img def preprocessing(img): # img = grayscale(img) img = equalize(img) img = img / 255 return img def read_imgs(image_dir, label = 0 ): # 读取图片 image_files = os.listdir(image_dir) images = [] labels = [] for image_file in image_files: image_path = os.path.join(image_dir, image_file) image = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE) # 以灰度模式读取图片 image = cv2.resize(image, ( 30 , 30 )) img = preprocessing(image) images.append(img) labels.append(label) return images, labels def test_predict(model): # 读取图片 image_dir = 'D:/welink/STOP/before' # images = read_imgs(image_dir) image_files = os.listdir(image_dir) images = [] for image_file in image_files: image_path = os.path.join(image_dir, image_file) image = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE) # 以灰度模式读取图片 image = cv2.resize(image, ( 30 , 30 )) img = preprocessing(image) img = img.reshape( 1 , 30 , 30 , 1 ) images.append(img) # PREDICT IMAGE predictions = model.predict(img) predict_x = model.predict(img) classIndex = np.argmax(predict_x) probabilityValue = np.amax(predictions) print ( "img path:" , image_file, " ==> " , str (classIndex) + " " + str (getCalssName(classIndex))) print ( str ( round (probabilityValue * 100 , 2 ) ) + "%" ) def refact_model(model): base_model = model # 移除最后的分类层 base_model = Model(inputs = base_model. input , outputs = base_model.layers[ - 2 ].output) # 添加一个新的分类层 output = Dense( 2 , activation = 'softmax' , name = 'new_dense' )(base_model.output) model = Model(inputs = base_model. input , outputs = output) # 编译模型 model. compile (optimizer = Adam(), loss = 'categorical_crossentropy' , metrics = [ 'accuracy' ]) return model def retrain_with2label(model): image_dir1 = 'D:/welink/STOP/14' image_dir2 = 'D:/welink/STOP/17' images1, labels1 = read_imgs(image_dir1, 0 ) images2, labels2 = read_imgs(image_dir2, 1 ) # 合并图片和标签 images = images1 + images2 labels = labels1 + labels2 images = np.array(images, dtype = 'float32' ) # 如果模型的输入形状是(30, 30, 1),那么我们需要增加一个维度 if model.input_shape[ - 1 ] = = 1 : images = np.expand_dims(images, axis = - 1 ) labels = np.array(labels) labels = to_categorical(labels, num_classes = 2 ) # 划分训练集和测试集 train_images, test_images, train_labels, test_labels = train_test_split(images, labels, test_size = 0.2 ) # 训练模型 model.fit(train_images, train_labels, validation_data = (test_images, test_labels), epochs = 10 ) def test_predict2(model): # 选择stop的图像,扰动前的 images, _ = read_imgs( 'D:/welink/STOP/before' ) if model.input_shape[ - 1 ] = = 1 : images = np.expand_dims(images, axis = - 1 ) preds = model.predict(images) print ( 'Predicted before:' , preds.argmax(axis = 1 )) return images def run_art(images): # 创建一个目标标签(我们希望模型将0 stop识别为1 no entry) target_label = to_categorical( 1 , num_classes = 2 ) target_label = np.tile(target_label, ( len (images), 1 )) # 创建ART分类器 classifier = TensorFlowV2Classifier( model = model, nb_classes = 2 , input_shape = ( 30 , 30 , 1 ), loss_object = tf.keras.losses.CategoricalCrossentropy(from_logits = True ), clip_values = ( 0 , 1 ) ) # 创建FGSM实例 attack = FastGradientMethod(estimator = classifier, targeted = True ) # 初始化对抗样本为原始图像 adv_images = np.copy(images) for i in range ( 100 ): # 最多迭代100次 # 生成对抗样本的扰动 perturbations = attack.generate(x = adv_images, y = target_label) - adv_images # 计算所有样本的平均扰动 avg_perturbation = np.mean(perturbations, axis = 0 ) # 将平均扰动添加到所有对抗样本上 adv_images + = avg_perturbation # 使用模型对对抗样本进行预测 preds = model.predict(adv_images) print ( 'Iteration:' , i, 'Predicted after:' , preds.argmax(axis = 1 )) # 如果所有的预测结果都为1,那么停止迭代 if np. all (preds.argmax(axis = 1 ) = = 1 ): break # 保存对抗样本 for i in range ( len (adv_images)): # 将图像的数据类型转换为uint8,并且将图像的值范围调整到[0, 255] img = (adv_images[i] * 255 ).astype(np.uint8) # 保存图像 cv2.imwrite(f 'traffic_adv_image_{i}.png' , img) # 归一化平均扰动并保存为图像 avg_perturbation = (avg_perturbation - np. min (avg_perturbation)) / (np. max (avg_perturbation) - np. min (avg_perturbation)) # 将平均扰动的值范围调整到[0, 255],并转换为uint8类型 avg_perturbation = (avg_perturbation * 255 ).astype(np.uint8) # 将灰度图像转换为RGB图像 avg_perturbation_rgb = cv2.cvtColor(avg_perturbation, cv2.COLOR_GRAY2RGB) # 保存图像 cv2.imwrite( 'traffic_avg_perturbation.png' , avg_perturbation_rgb) if __name__ = = "__main__" : # 找到一个训练好的,识别交通信号牌的模型: https://github.com/Daulettulegenov/TSR_CNN model = load_model(r 'D:\source\competition\TSR_CNN-main\CNN_model_3.h5' ) # 预测原始的输出类型,可以看到并不能正确的分类,因为是中文字幕 停!!!!而不是 STOP test_predict(model) # 因此,需要迁移训练,让其识别中文的“停” model = refact_model(model) # 测试是否可以识别中文的停 retrain_with2label(model) # 预测新的输出类型,可以看到能正确的分类,即便是中文的停!!! images = test_predict2(model) # 生成扰动图像,让其扰动,识别为no entry,保存扰动图像 run_art(images) |
效果:
Predicted before: [0 0 0 0 0 0 0 0 0 0]
output, from_logits = _get_logits(....
1/1 [==============================] - 0s 38ms/step
Iteration: 0 Predicted after: [1 1 0 1 0 0 1 0 1 0]
1/1 [==============================] - 0s 46ms/step
Iteration: 1 Predicted after: [1 1 1 1 1 1 1 1 1 1]
生成的对抗样本:
依稀可见“停”
扰动图像:
代码说明:这份代码的主要目的是使用深度学习模型来识别交通信号牌,并使用对抗性攻击来生成能够误导模型的对抗样本。
以下是代码的主要部分的解释:
1. getCalssName(classNo): 这个函数根据类别编号返回对应的交通信号牌的名称。
2. grayscale(img), equalize(img), preprocessing(img): 这些函数用于图像预处理,包括将图像转换为灰度图像,进行直方图均衡化,以及归一化。
3. read_imgs(image_dir, label=0): 这个函数读取指定目录下的所有图像,并返回图像数据和对应的标签。
4. test_predict(model): 这个函数读取指定目录下的所有图像,然后使用模型进行预测,并打印出预测结果。
5. refact_model(model): 这个函数修改模型的结构,移除最后的分类层,然后添加一个新的分类层。
6. retrain_with2label(model): 这个函数读取两个目录下的所有图像,然后使用这些图像和对应的标签来训练模型。
7. test_predict2(model): 这个函数读取指定目录下的所有图像,然后使用模型进行预测,并返回预测结果和图像数据。
8. run_art(images): 这个函数使用对抗性攻击来生成对抗样本,并保存对抗样本和平均扰动。
在if __name__ == "__main__"部分,代码首先加载一个预训练的模型,然后使用这个模型来预测原始的交通信号牌图像。然后,代码修改模型的结构,并使用新的数据来训练模型。最后,代码使用新的模型来预测原始的交通信号牌图像,并使用对抗性攻击来生成对抗样本。
1. getCalssName(classNo): 这个函数根据类别编号返回对应的交通信号牌的名称。
2. grayscale(img), equalize(img), preprocessing(img): 这些函数用于图像预处理,包括将图像转换为灰度图像,进行直方图均衡化,以及归一化。
3. read_imgs(image_dir, label=0): 这个函数读取指定目录下的所有图像,并返回图像数据和对应的标签。
4. test_predict(model): 这个函数读取指定目录下的所有图像,然后使用模型进行预测,并打印出预测结果。
5. refact_model(model): 这个函数修改模型的结构,移除最后的分类层,然后添加一个新的分类层。
6. retrain_with2label(model): 这个函数读取两个目录下的所有图像,然后使用这些图像和对应的标签来训练模型。
7. test_predict2(model): 这个函数读取指定目录下的所有图像,然后使用模型进行预测,并返回预测结果和图像数据。
8. run_art(images): 这个函数使用对抗性攻击来生成对抗样本,并保存对抗样本和平均扰动。
在if __name__ == "__main__"部分,代码首先加载一个预训练的模型,然后使用这个模型来预测原始的交通信号牌图像。然后,代码修改模型的结构,并使用新的数据来训练模型。最后,代码使用新的模型来预测原始的交通信号牌图像,并使用对抗性攻击来生成对抗样本。
样本下载:
交通信号灯 https://www.kaggle.com/datasets/meowmeowmeowmeowmeow/gtsrb-german-traffic-sign
标签:
安全分析
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」
2019-10-30 SQL注入中的WAF绕过
2018-10-30 python daal test
2018-10-30 python dict 构造函数性能比较
2018-10-30 CNN autoencoder 进行异常检测——TODO,使用keras进行测试
2018-10-30 利用CNN进行流量识别 本质上就是将流量视作一个图像
2018-10-30 Deep Belief Network简介——本质上是在做逐层无监督学习,每次学习一层网络结构再逐步加深网络
2018-10-30 python pipe stdout 实现cat|grep 功能