赞
踩
总体流程步骤
如下图,分别是由SAR卫星获取的极化SAR图像及其标签图
根据不同的颜色标签(红、绿、黄、白)可以将原图分为四个部分(下图只有三部分,白色区域图片没有展示)
对于图片中有效区域进行裁切分割,按照类型分别存储在不同的文件夹中作为训练数据。
每次运行该程序选择某一文件夹的所有图片进行训练得到效果图,直到将所有类型图片都训练完成一遍
# 生成对抗网络模型,训练模型生成仿真图片。 import argparse import torch import torchvision import torchvision.utils as vutils import torch.nn as nn import numpy as np from random import randint import matplotlib.pyplot as plt class NetG(nn.Module): def __init__(self, ngf, nz): super(NetG, self).__init__() # layer1输入的是一个100x1x1的随机噪声, 输出尺寸(ngf*8)x4x4 # Sequential是一个时序容器modules会以他们传入时的顺序添加到容器中 # ConvTranspose2d是二维卷积转置操作,将普通卷积的输出作为转置卷积的输入 # BatchNorm2d是一个批标准化操作,对每一个小批量中计算各维度的均值和标准差 # inplace=True代表的对源数据进行原地操作 self.layer1 = nn.Sequential( # 参数分别有:输入通道数,输出通道数,卷积核大小,计算步长大小,补充0的层数,偏置 nn.ConvTranspose2d(nz, ngf * 8, kernel_size=4, stride=1, padding=0, bias=False), nn.BatchNorm2d(ngf * 8), nn.ReLU(inplace=True) ) # layer2输出尺寸(ngf*4)x8x8 self.layer2 = nn.Sequential( nn.ConvTranspose2d(ngf * 8, ngf * 4, 4, 2, 1, bias=False), nn.BatchNorm2d(ngf * 4), nn.ReLU(inplace=True) ) # layer3输出尺寸(ngf*2)x16x16 self.layer3 = nn.Sequential( nn.ConvTranspose2d(ngf * 4, ngf * 2, 4, 2, 1, bias=False), nn.BatchNorm2d(ngf * 2), nn.ReLU(inplace=True) ) # layer4输出尺寸(ngf)x32x32 self.layer4 = nn.Sequential( nn.ConvTranspose2d(ngf * 2, ngf, 4, 2, 1, bias=False), nn.BatchNorm2d(ngf), nn.ReLU(inplace=True) ) # layer5输出尺寸 3x96x96 self.layer5 = nn.Sequential( nn.ConvTranspose2d(ngf, 3, 5, 3, 1, bias=False), nn.Tanh() ) # 定义NetG的前向传播 def forward(self, x): out = self.layer1(x) out = self.layer2(out) out = self.layer3(out) out = self.layer4(out) out = self.layer5(out) return out # 定义鉴别器网络D class NetD(nn.Module): def __init__(self, ndf): super(NetD, self).__init__() # layer1 输入 3 x 96 x 96, 输出 (ndf) x 32 x 32 self.layer1 = nn.Sequential( nn.Conv2d(3, ndf, kernel_size=5, stride=3, padding=1, bias=False), nn.BatchNorm2d(ndf), nn.LeakyReLU(0.2, inplace=True) ) # layer2 输出 (ndf*2) x 16 x 16 self.layer2 = nn.Sequential( nn.Conv2d(ndf, ndf * 2, 4, 2, 1, bias=False), nn.BatchNorm2d(ndf * 2), nn.LeakyReLU(0.2, inplace=True) ) # layer3 输出 (ndf*4) x 8 x 8 self.layer3 = nn.Sequential( nn.Conv2d(ndf * 2, ndf * 4, 4, 2, 1, bias=False), nn.BatchNorm2d(ndf * 4), nn.LeakyReLU(0.2, inplace=True) ) # layer4 输出 (ndf*8) x 4 x 4 self.layer4 = nn.Sequential( nn.Conv2d(ndf * 4, ndf * 8, 4, 2, 1, bias=False), nn.BatchNorm2d(ndf * 8), nn.LeakyReLU(0.2, inplace=True) ) # layer5 输出一个数(概率) self.layer5 = nn.Sequential( nn.Conv2d(ndf * 8, 1, 4, 1, 0, bias=False), nn.Sigmoid() ) # 定义NetD的前向传播 def forward(self,x): out = self.layer1(x) out = self.layer2(out) out = self.layer3(out) out = self.layer4(out) out = self.layer5(out) return out parser = argparse.ArgumentParser() parser.add_argument('--batchSize', type=int, default=64) # 每次处理的图片数量 parser.add_argument('--imageSize', type=int, default=96) # 图片像素大小 parser.add_argument('--nz', type=int, default=100, help='size of the latent z vector') # 图片信息维度 parser.add_argument('--ngf', type=int, default=64) parser.add_argument('--ndf', type=int, default=64) parser.add_argument('--epoch', type=int, default=4000, help='number of epochs to train for') parser.add_argument('--lr', type=float, default=0.0002, help='learning rate, default=0.0002') parser.add_argument('--beta1', type=float, default=0.5, help='beta1 for adam. default=0.5') parser.add_argument('--data_path', default='data/', help='folder to train data') parser.add_argument('--outf', default='img/', help='folder to output images and model checkpoints') opt = parser.parse_args() # 图像读入与预处理 包括统一大小、转化为张量、归一化操作 transforms = torchvision.transforms.Compose([ torchvision.transforms.Scale(opt.imageSize), torchvision.transforms.ToTensor(), torchvision.transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)), ]) # 将指定路径的数据集加载到程序中 dataset = torchvision.datasets.ImageFolder(opt.data_path, transform=transforms) dataloader = torch.utils.data.DataLoader( dataset=dataset, batch_size=opt.batchSize, shuffle=True, drop_last=True, # 丢弃最后一批数据 ) # 定义是否使用GPU device = torch.device("cuda" if torch.cuda.is_available() else "cpu") netG = NetG(opt.ngf, opt.nz).to(device) netD = NetD(opt.ndf).to(device) # 以以二分类的交叉熵作为损失函数,以Adam优化函数优化随机目标函数 criterion = nn.BCELoss() optimizerG = torch.optim.Adam(netG.parameters(), lr=opt.lr, betas=(opt.beta1, 0.999)) optimizerD = torch.optim.Adam(netD.parameters(), lr=opt.lr, betas=(opt.beta1, 0.999)) # 将一个批次的数据传入label中 label = torch.FloatTensor(opt.batchSize) real_label = 1 fake_label = 0 loss_D = [] loss_G = [] for epoch in range(1, opt.epoch + 1): for i, (imgs, _) in enumerate(dataloader): # 固定生成器G,训练鉴别器D,将梯度初始化为0 optimizerD.zero_grad() # 让D尽可能的把真图片判别为1,计算D网络判别结果和实际结果的的交叉熵损失, imgs=imgs.to(device) output = netD(imgs) label.data.fill_(real_label) label=label.to(device) errD_real = criterion(output, label) errD_real.backward() # 让D尽可能把假图片判别为0 label.data.fill_(fake_label) noise = torch.randn(opt.batchSize, opt.nz, 1, 1) noise=noise.to(device) fake = netG(noise) # 生成假图 output = netD(fake.detach()) # 避免梯度传到G,因为不需要计算G的梯度。不加则反向传播会进行计算,节约时间和内存 errD_fake = criterion(output, label) errD_fake.backward() errD = errD_fake + errD_real optimizerD.step() # 固定鉴别器D,训练生成器G optimizerG.zero_grad() # 让D尽可能把G生成的假图判别为1 label.data.fill_(real_label) label = label.to(device) output = netD(fake) errG = criterion(output, label) errG.backward() optimizerG.step() # 每两个epoch将值填入loss_D和l中H中,作为后期画图用数据 if epoch % 2 == 0: loss_D.append(errD.item()) loss_G.append(errG.item()) # 将数据显示到控制台,直观看出当前两个网络的损失函数变化情况 print('[%d/%d][%d/%d] Loss_D: %.3f Loss_G %.3f' % (epoch, opt.epoch, i, len(dataloader), errD.item(), errG.item())) # 每三十个epoch保存当前网络G生成图片效果 if epoch % 30 == 0: vutils.save_image(fake.data, '%s/fake_samples_epoch_%03d.png' % (opt.outf, epoch), normalize=True) # 每500epoch保存当前网络G和网络D的神经模型作为后续使用 if epoch % 500 == 0: torch.save(netG.state_dict(), '%s/netG_%03d.pth' % (opt.outf, epoch)) torch.save(netD.state_dict(), '%s/netD_%03d.pth' % (opt.outf, epoch)) # 将损失函数变化显示出来 # index = np.arange(100) # y1 = loss_D # y2 = loss_G # fig = plt.figure() # ax1 = fig.add_subplot(111) # ax1.plot(index, y1) # ax1.set_xlabel('epoch') # ax1.set_label('loss') # ax1.set_ylabel('loss') # ax1.set_xlim(0, 120) # ax1.set_title('loss and correct') # ax2 = ax1.twinx() # ax2.set_label('correct') # ax2.plot(index, y2, 'r') # ax2.set_ylabel('correct') # plt.show()
生成图片效果如下图所示:
得到生成图片后需要进行裁切处理,裁切方法如下
# -*- coding: utf-8 -*- # 将生成网络模型的生成图片进行处理和切割。 from PIL import Image import sys # 将图片填充为正方形 def fill_image(image): width, height = image.size # 选取长和宽中较大值作为新图片的 new_image_length = width if width > height else height # 生成新图片[白底] new_image = Image.new(image.mode, (new_image_length, new_image_length), color='blue') # 将之前的图粘贴在新图上,居中 if width > height: # 原图宽大于高,则填充图片的竖直维度 # (x,y)二元组表示粘贴上图相对下图的起始位置 new_image.paste(image, (0, int((new_image_length - height) / 2))) else: new_image.paste(image, (int((new_image_length - width) / 2), 0)) return new_image def cut_image(image): width, height = image.size item_width = int(width / 6) box_list = [] # (left, upper, right, lower) for i in range(0, 6): # 两重循环,生成若干张图片基于原图的位置 for j in range(0, 6): # print((i*item_width,j*item_width,(i+1)*item_width,(j+1)*item_width)) box = (j*item_width, i*item_width, (j+1)*item_width, (i+1)*item_width) box_list.append(box) image_list = [image.crop(box) for box in box_list] return image_list #保存 def save_images(image_list): index = 1 for image in image_list: image.save(r'H:\new_cutSAR\realSAR\pau\label/'+str(index) + '.png', 'PNG') index += 1 if __name__ == '__main__': file_path = r"H:\new_cutSAR\realSAR\pau/xx2.jpg" image = Image.open(file_path) #image.show() image = fill_image(image) image_list = cut_image(image) save_images(image_list)
GAN训练过程损失函数变化
在得到GAN生成的图片后,以文件夹名作为label分别存储,作为CNN的训练数据进行训练
# encoding=utf-8 # 以卷积神经网络来对图像进行模型训练和分类工作 import torch import torchvision import torchvision.transforms as transforms import torchvision.utils as vutils import torch.nn as nn import torch.nn.functional as F from torch.autograd import Variable import torch.optim as optim import matplotlib.pyplot as plt import numpy as np import os.path from PIL import Image class Net(nn.Module): # 定义网络,继承torch.nn.Module def __init__(self): super(Net, self).__init__() self.conv1 = nn.Conv2d(3, 6, 5) # 卷积层 self.pool = nn.MaxPool2d(2, 2) # 池化层 self.conv2 = nn.Conv2d(6, 16, 5) # 卷积层 self.fc1 = nn.Linear(16 * 5 * 5, 120) # 全连接层 self.fc2 = nn.Linear(120, 84) self.fc3 = nn.Linear(84, 10) # 10个输出 def forward(self, x): # 前向传播 x = self.pool(F.relu(self.conv1(x))) # F就是torch.nn.functional x = self.pool(F.relu(self.conv2(x))) x = x.view(-1, 16 * 5 * 5) # .view( )是一个tensor的方法,使得tensor改变size但是元素的总数是不变的。 # 从卷基层到全连接层的维度转换 x = F.relu(self.fc1(x)) x = F.relu(self.fc2(x)) x = self.fc3(x) return x # 分类类型标识 classes = ('green', 'red', 'white', 'yellow') # 加载训练CNN网络的数据样本 def loadtraindata(): path = r"E:\pythontest\new_cutSAR\train/" # 路径 trainset = torchvision.datasets.ImageFolder(path, transform=transforms.Compose([ transforms.Resize((32, 32)), # 将图片缩放到指定大小(h,w)或者保持长宽比并缩放最短的边到int大小 transforms.CenterCrop(32), transforms.ToTensor()]) ) trainloader = torch.utils.data.DataLoader(trainset, batch_size=4, shuffle=True, num_workers=5) return trainloader # 加载分类测试用数据 def loadtestdata(): path = r"E:\pythontest\new_cutSAR\test/" testset = torchvision.datasets.ImageFolder(path, transform=transforms.Compose([ transforms.Resize((32, 32)), # 将图片缩放到指定大小(h,w)或者保持长宽比并缩放最短的边到int大小 transforms.ToTensor()]) ) testloader = torch.utils.data.DataLoader(testset, batch_size=262, shuffle=False, num_workers=5) return testloader # 训练CNN网络 def trainandsave(): trainloader = loadtraindata() # 神经网络结构 net = Net() optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9) # 学习率为0.001 criterion = nn.CrossEntropyLoss() # 损失函数也可以自己定义,我们这里用的交叉熵损失函数 cor = [] # 定义正确率和损失函数随epoch增加的变化 los = [] max = 0 # 训练部分 for epoch in range(200): # 训练的数据量为200个epoch,每个epoch为一个循环 # 每个epoch要训练所有的图片,每训练完成50张便打印一下训练的效果(loss值) running_loss = 0.0 # 定义一个变量方便我们对loss和correct进行输出 correct = 0.0 for i, data in enumerate(trainloader, 0): # 这里我们遇到了第一步中出现的trailoader,代码传入数据 # enumerate是python的内置函数,既获得索引也获得数据 # get the inputs inputs, labels = data # data是从enumerate返回的data,包含数据和标签信息,分别赋值给inputs和labels # wrap them in Variable inputs, labels = Variable(inputs), Variable(labels) # 转换数据格式用Variable optimizer.zero_grad() # 梯度置零,因为反向传播过程中梯度会累加上一次循环的梯度 # forward + backward + optimize outputs = net(inputs) # 把数据输进CNN网络net # 正确率 _, predicted = torch.max(outputs.data, 1) correct += (predicted == labels.data).sum().item() loss = criterion(outputs, labels) # 计算损失值 loss.backward() # loss反向传播 该图会动态生成并自动微分,会自动计算图中参数的导数; optimizer.step() # 反向传播后参数更新 running_loss += loss.item() # loss累加 # 限制训练次数不能超过最大值 if i>max: max = i if i % 50 == 49: print('[%d, %5d] loss: %.3f acc: %.1f%%' % (epoch + 1, i + 1, running_loss / 50, (50*correct)/100)) # 然后再除以200,就得到这两百次的平均损失值 los.append(running_loss/50) cor.append((50*correct)/100) running_loss = 0.0 # 这一个50次结束后,就把running_loss归零,下一个200次继续使用 correct = 0.0 print(max) # 展示训练效果变化图片 index = np.arange(1000) y1 = los y2 = cor fig = plt.figure() ax1 = fig.add_subplot(111) ax1.plot(index, y1) ax1.set_xlabel('epoch') ax1.set_label('loss') ax1.set_ylabel('loss') ax1.set_xlim(0, 200) ax1.set_title('loss and correct') ax2 = ax1.twinx() ax2.set_label('correct') ax2.plot(index, y2, 'r') ax2.set_ylabel('correct') plt.show() print('Finished Training') # 保存神经网络 torch.save(net, 'net.pkl') # 保存整个神经网络的结构和模型参数 torch.save(net.state_dict(), 'net_params.pkl') # 只保存神经网络的模型参 # trainandsave() # 加载上次训练结果模型,方便在上次基础上继续训练 def reload_net(): trainednet = torch.load('net.pkl') return trainednet def imshow(img): img = img / 2 + 0.5 # unnormalize npimg = img.numpy() plt.imshow(np.transpose(npimg, (1, 2, 0))) plt.show() def alter(path, object): # 更改图片像素大小 s = os.listdir(path) count = 1 for i in s: document = os.path.join(path, i) img = Image.open(document) out = img.resize((96, 96)) listStr = [str(count)] fileName = ''.join(listStr) out.save(object+os.sep+'%s.jpg' % fileName) count = count + 1 def test(): testloader = loadtestdata() net = reload_net() # 使用模型 dataiter = iter(testloader) images, labels = dataiter.next() # print('\nGroundTruth:' , " ".join('%5s' % classes[labels[j]] for j in range(262))) # 打印前25个GT(test集里图片的标签) outputs = net(Variable(images)) _, predicted = torch.max(outputs.data, 1) print('Predicted: ', " ".join('%5s' % classes[predicted[j]] for j in range(262))) # 定义图片格式 file_path = r'E:\pythontest\new_cutSAR\train\red96/red1.jpg' image1 = Image.open(file_path) # 将数据集的内容分类后分别放在各自的文件夹中 for j in range(262): if classes[predicted[j]] == 'green': vutils.save_image(images[j], r'E:\pythontest\new_cutSAR\result\green/%s%05d.jpg' % (classes[labels[j]], j)) # 对于不同的类别分别生成不同的图像标签 new_image = Image.new(image1.mode, (32, 32), color='green') new_image.save( r'E:\pythontest\new_cutSAR\label\all/%s%05d.jpg' % (classes[labels[j]], j)) elif classes[predicted[j]] == 'red': vutils.save_image(images[j], r'E:\pythontest\new_cutSAR\result\red/%s%05d.jpg' % (classes[labels[j]], j)) new_image = Image.new(image1.mode, (32, 32), color='red') new_image.save(r'E:\pythontest\new_cutSAR\label\all/%s%05d.jpg' % (classes[labels[j]], j)) elif classes[predicted[j]] == 'white': vutils.save_image(images[j], r'E:\pythontest\new_cutSAR\result\white/%s%05d.jpg' % (classes[labels[j]], j)) new_image = Image.new(image1.mode, (32, 32), color='white') new_image.save(r'E:\pythontest\new_cutSAR\label\all/%s%05d.jpg' % (classes[labels[j]], j)) elif classes[predicted[j]] == 'yellow': vutils.save_image(images[j], r'E:\pythontest\new_cutSAR\result\yellow/%s%05d.jpg' % (classes[labels[j]], j)) new_image = Image.new(image1.mode, (32, 32), color='yellow') new_image.save(r'E:\pythontest\new_cutSAR\label\all/%s%54d.jpg' % (classes[labels[j]], j)) cc = 0 # 识别正确图片数量 for j in range(262): if classes[labels[j]] == classes[predicted[j]]: cc += 1 print(cc) index = np.arange(263) # 4097 real = [] predi = [] real.append('xx') predi.append('xx') for j in range(262): real.append(classes[labels[j]]) predi.append(classes[predicted[j]]) width = 0.3 plt.bar(left=index, height=real, width=width, color='yellow', label=u'real') plt.bar(left=index + width, height=predi, width=width, color='green', label=u'predict') plt.xlabel('epoch') plt.ylabel('real/predict') plt.legend(loc='best') plt.show() # 打印前25个预测值 # imshow(torchvision.utils.make_grid(images, nrow=5)) # nrow是每行显示的图片数量,缺省值为8 # test() correct, total = 0, 0 with torch.no_grad(): for images, labels in testloader: outputs = net(images) _, predicted = torch.max(outputs, 1) total += labels.size(0) correct += (labels == predicted).sum().item() print('total: %d' % total) print('Accuracy of the network on the 10000 test images: %d %%' % ( 100 * correct / total)) # 训练CNN网络是,注释test()方法,执行trainandsave() # 使用CNN网络进行分类,则注释trainandsave()方法,执行test()方法 if __name__ == "__main__": test() # trainandsave()
CNN训练正确率和损失随训练次数变化情况
随机选取三十张图片,显示CNN网络判别结果和实际类型的对比图
将一张200×200大小的图像以20×20的窗口切割,从左到右,从上到下,每次移动一个像素点,总共得到40000张小图
import cv2 img = cv2.imread(r"E:\pythontest\new_cutSAR\realSAR\pau\yuan/3.png") print(img.shape) i = 0 j = 0 for i in range(0, 200, 1): for j in range(0, 200, 1): num = i * 200 + j # num = (i/20) * 10 + j/20 cropped = img[i:i+20, j:j+20] # 裁剪坐标为[y0:y1, x0:x1] cv2.imwrite(r"E:\pythontest\new_cutSAR\cutPixel\main/%05d.jpg" % num, cropped) # y%d_x%d
将这40000张图片按序输入到CNN网络模型中进行判别,依据判别结果生成红、黄、绿、白四种颜色的像素块,存储到另一文件夹中
# 将40000张由小像素点图像重组为一张200×200的大图 import PIL.Image as Image import os IMAGES_PATH = r'E:\pythontest\new_cutSAR\max3_3\yuan/' # 图片集地址 # IMAGES_PATH = r'E:\pythontest\new_cutSAR\cutPixelResult/' # 图片集地址 IMAGES_FORMAT = ['.png', '.JPG'] # 图片格式 IMAGE_SIZE = 400 # 每张小图片的大小 IMAGE_ROW = 3 # 图片间隔,也就是合并成一张图后,一共有几行 IMAGE_COLUMN = 3 # 图片间隔,也就是合并成一张图后,一共有几列 IMAGE_SAVE_PATH = 'maxyuan.png' # 图片转换后的地址 # 获取图片集地址下的所有图片名称 image_names = [name for name in os.listdir(IMAGES_PATH) for item in IMAGES_FORMAT if os.path.splitext(name)[1] == item] # 简单的对于参数的设定和实际图片集的大小进行数量判断 if len(image_names) != IMAGE_ROW * IMAGE_COLUMN: raise ValueError("合成图片的参数和要求的数量不能匹配!") # 定义图像拼接函数 def image_compose(): to_image = Image.new('RGB', (IMAGE_COLUMN * IMAGE_SIZE, IMAGE_ROW * IMAGE_SIZE)) # 创建一个新图 # 循环遍历,把每张图片按顺序粘贴到对应位置上 for y in range(1, IMAGE_ROW + 1): for x in range(1, IMAGE_COLUMN + 1): from_image = Image.open(IMAGES_PATH + image_names[IMAGE_COLUMN * (y - 1) + x - 1]).resize( (IMAGE_SIZE, IMAGE_SIZE), Image.ANTIALIAS) to_image.paste(from_image, ((x - 1) * IMAGE_SIZE, (y - 1) * IMAGE_SIZE)) return to_image.save(IMAGE_SAVE_PATH) # 保存新图 image_compose() # 调用函数
重组结果
# -*- coding: utf-8 -*- #feimengjuan # 比较两张图像的相似度 import cv2 import numpy as np from matplotlib import pyplot as plt # 平均哈希算法计算 def classify_aHash(image1,image2): image1 = cv2.resize(image1,(200,200)) image2 = cv2.resize(image2,(200,200)) gray1 = cv2.cvtColor(image1,cv2.COLOR_BGR2GRAY) gray2 = cv2.cvtColor(image2,cv2.COLOR_BGR2GRAY) hash1 = getHash(gray1) hash2 = getHash(gray2) return Hamming_distance(hash1,hash2) def classify_pHash(image1,image2): image1 = cv2.resize(image1,(256,256)) image2 = cv2.resize(image2,(256,256)) gray1 = cv2.cvtColor(image1,cv2.COLOR_BGR2GRAY) gray2 = cv2.cvtColor(image2,cv2.COLOR_BGR2GRAY) # 将灰度图转为浮点型,再进行dct变换 dct1 = cv2.dct(np.float32(gray1)) dct2 = cv2.dct(np.float32(gray2)) # 取左上角的8*8,这些代表图片的最低频率 # 这个操作等价于c++中利用opencv实现的掩码操作 # 在python中进行掩码操作,可以直接这样取出图像矩阵的某一部分 dct1_roi = dct1[0:256,0:256] dct2_roi = dct2[0:256,0:256] hash1 = getHash(dct1_roi) hash2 = getHash(dct2_roi) return Hamming_distance(hash1,hash2) # 输入灰度图,返回hash def getHash(image): avreage = np.mean(image) hash = [] for i in range(image.shape[0]): for j in range(image.shape[1]): if image[i,j] > avreage: hash.append(1) else: hash.append(0) return hash # 计算汉明距离 def Hamming_distance(hash1,hash2): num = 0 for index in range(len(hash1)): if hash1[index] != hash2[index]: num += 1 return num if __name__ == '__main__': img1 = cv2.imread("max_label.png") #cv2.imshow('img1',img1) img2 = cv2.imread("maxps1.png") #cv2.imshow('img2',img2) #degree1 = classify_gray_hist(img1,img2) #degree2 = classify_hist_with_split(img1,img2) degree3 = classify_aHash(img1,img2) correct3 = (40000-degree3)/40000.0 *100 #degree4 = classify_pHash(img1,img2) #correct4 = (40000-degree4)/40000.0 *100 #print("灰度直方图:%d" %degree1) #print("每个通道直方图%d" %degree2) print("平均哈希值:%.3f %%" %correct3) #print("感知哈希值:%.3f %%" %correct4) cv2.waitKey(0) # 平均哈希法(aHash) # 此算法是基于比较灰度图每个像素与平均值来实现的 # 一般步骤: # 1.缩放图片,一般大小为8*8,64个像素值。 # 2.转化为灰度图 # 3.计算平均值:计算进行灰度处理后图片的所有像素点的平均值,直接用numpy中的mean()计算即可。 # 4.比较像素灰度值:遍历灰度图片每一个像素,如果大于平均值记录为1,否则为0. # 5.得到信息指纹:组合64个bit位,顺序随意保持一致性。 # 最后比对两张图片的指纹,获得汉明距离即可。
参考博客:https://blog.csdn.net/jizhidexiaoming/article/details/97108754
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。