首页 > 其他分享 >使用IBM ART库生成交通信号牌的攻击样本

使用IBM ART库生成交通信号牌的攻击样本

时间:2023-10-30 12:00:25浏览次数:29  
标签:model elif return IBM image images ART 交通信号 classNo

目标:生成对抗样本,扰动图像,让原本是“停”的信号牌识别为“禁止驶入”:

 

代码如下(注意,因为我找的cnn原始模型支持的是灰度图像,所以彩色的对抗样本还需要修改代码):

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__"部分,代码首先加载一个预训练的模型,然后使用这个模型来预测原始的交通信号牌图像。然后,代码修改模型的结构,并使用新的数据来训练模型。最后,代码使用新的模型来预测原始的交通信号牌图像,并使用对抗性攻击来生成对抗样本。   样本下载: 交通信号灯 https://www.kaggle.com/datasets/meowmeowmeowmeowmeow/gtsrb-german-traffic-sign  

 

标签:model,elif,return,IBM,image,images,ART,交通信号,classNo
From: https://www.cnblogs.com/bonelee/p/17797484.html

相关文章

  • spring-boot-starter-redis 熟练运用
    Redis的Java客户端很多,官方推荐的有三种:Jedis  (javaredis)RedissonLettuceSpring对Redis客户端进行了整合,提供了SpringDataRedis,在SpringBoot项目中还提供了对应的Starter,即spring-boot-starter-data-redis。Jedis(了解)项目准备Jedis是Redis的Java版本客户端,现......
  • centos7.9重启网卡提示Failed to start LSB: Bring up/down networking.
    前几天给一台机器状态centos7.9系统,设备有2个网口,今天重启网卡一直失败,查看network状态,怀疑是eth0网卡有问题查看eth0的网卡配置,发现是eth0网卡的BOOTPROTO=dhcp,且ONBOOT=yes,但eth0网口没插网线,这导致重启网卡时,一直重启eth0,但是没插网线一直失败。解决方案:把eth0网卡的ONB......
  • 编写一个自己的SpringBoot Starter
    我们用SpringBoot的时候发现有很多starter,比如spring-boot-starter-web等,对于SpringBoot的官方starter,基本上是以spring-boot-starter-xxx来命名的,对于非官方的一些包来说,我们该怎样将自己的包与SpringBoot结合起来呢?在SpringBoot的官方文档中,有这样一章,CreatingYourOwnStarter......
  • Failed to start The nginx HTTP and reverse proxy server.
    本章教程主要分享一下,当nginx启动时,遇到报这个错误时的一个解决思路。 目录 1、观察报错信息 2、尝试性解决 1、观察报错信息根据日志的信息,我们至少可以知道2个比较关键的信息。1、操作用户执行命令是在非root权限下进行操作的。2、Addressalreadyinuse这个很明显:意思就......
  • 一键解决UnicodeDecodeError: ‘utf-8’ codec can’t decode byte 0xa1 in position
    UnicodeDecodeError:‘utf-8’codeccan’tdecodebyte0xa1inposition0:invalidstartbyte文章目录问题描述解决思路解决方法问题描述UnicodeDecodeError:‘utf-8’codeccan’tdecodebyte0xa1inposition0:invalidstartbyte解决思路这个错误表明你正在试图以......
  • Flutter/Dart第18天:Dart特性之可调用对象
    Dart官方文档:https://dart.dev/language/callable-objects重要说明:本博客基于Dart官网文档,但并不是简单的对官网进行翻译,在覆盖核心功能情况下,我会根据个人研发经验,加入自己的一些扩展问题和场景验证。可调用对象:Dart实例如果实现了call()方法,那么实例就可以像函数那样被调用,这......
  • IBM V7000微码升级方案
    目录第一章升级时间3第二章微码升级步骤3第三章应急预案9升级时间每一个结点的软件升级耗时大约30–40分钟。GUI会显示“Complete”。整个V7000的软件升级耗时大约90-120分钟。注意:微码升级过程中,可能会导致主机意外的硬件或是软件故障,需要为修复这些故障预留足够的服务......
  • IBM V7000更换硬盘步骤
    诊断过程最常见情况,坏盘为脱机/OFFLINE状态:比较罕见情况,坏盘为已降级/degraded状态:更换步骤情况1,坏盘为脱机/offline状态:事件中有关硬盘的报错可能出现在多条事件/event里边,系统会自动分析并根据情况提示优先修复哪条事件/event,根据系统建议选中所提示的事件,右键修复,正常走修复流程......
  • Spartacus lazy loading 模块中的配置管理
    如果在懒加载模块中提供了额外的配置,组合商店前端将其合并到全局应用配置中,以支持现有组件和服务的懒加载场景。在大多数情况下,尤其是当懒加载模块主要提供默认配置时,这种方式都能可靠地工作。然而,如果过度使用,特别是当两个模块为配置的同一部分提供不同的配置时,可能会导致问题。......
  • C#详解-Contains、StartsWith、EndsWith、Indexof、lastdexof 怎样性能最优
    简介:在C#中Contains、StarsWith和EndWith、IndexOf都是字符串函数。1.Contains函数用于判断一个字符串是否包含指定的子字符串,返回一个布尔值(True或False)。2.StartsWith函数用于判断一个字符串是否以指定的子字符串开头,返回一个布尔值(True或False)。3.EndsWith函数用于判断一个字......