图像预处理及扩增

  • 判断图片是否为灰度图片
  • 批量给图片文件重命名
    • 给一批文件重命名
    • 把一批文件顺序打乱重命名
  • 图像旋转/翻转
  • 将图像和对应的xml标签文件都翻转
  • 将目标所在区域裁剪出来
    • 方法一
    • 方法二:
    • 方法三
  • 裁剪并纠偏
  • 图像扩增方法合集(对单张图片)

容易出现的报错:

cv2.error: OpenCV(4.7.0) D:\a\opencv-python\opencv-python\opencv\modules\imgcodecs\src\loadsave.cpp:692: error: (-2:Unspecified error) could not find a writer for the specified extension in function 'cv::imwrite_'

错误原因通常为保存的路径不正确:

cv2.imwrite('./crop_images/origin_imgs', roi)

应改为:

cv2.imwrite(os.path.join('./crop_images/origin_imgs', img_name), roi)

即第一个参数应该写到文件的名称,而不能只写到文件夹就停止。

判断图片是否为灰度图片

灰度图片和黑白图片有些相似,但并不完全相同。

灰度图片是指每个像素点的颜色由灰度值来表示,通常使用8位无符号整数(0-255)表示。灰度图像中的每个像素点可能具有不同的灰度值,因此图像中可能会有许多不同的灰度级别。

黑白图片通常指的是二值图像,其中只有两种像素值,通常是黑色和白色。黑白图像中的每个像素点只有两种可能的取值,因此图像中只有两个灰度级别。

虽然灰度图像和黑白图像都只是使用灰度值来表示图像中的像素点,但它们在像素的取值范围和数量上有所不同。

# 黑白照片(灰度图)识别
def isGrayMap(img, threshold = 15):"""入参:img:PIL读入的图像threshold:判断阈值,图片3个通道间差的方差均值小于阈值则判断为灰度图。阈值设置的越小,容忍出现彩色面积越小;设置的越大,那么就可以容忍出现一定面积的彩色,例如微博截图。如果阈值设置的过小,某些灰度图片会被漏检,这是因为某些黑白照片存在偏色,例如发黄的黑白老照片、噪声干扰导致灰度图不同通道间值出现偏差(理论上真正的灰度图是RGB三个通道的值完全相等或者只有一个通道,然而实际上各通道间像素值略微有偏差看起来仍是灰度图)出参:bool值"""if len(img.getbands()) == 1:return Trueimg1 = np.asarray(img.getchannel(channel=0), dtype=np.int16)img2 = np.asarray(img.getchannel(channel=1), dtype=np.int16)img3 = np.asarray(img.getchannel(channel=2), dtype=np.int16)diff1 = (img1 - img2).var()diff2 = (img2 - img3).var()diff3 = (img3 - img1).var()diff_sum = (diff1 + diff2 + diff3) / 3.0if diff_sum <= threshold:return Trueelse:return False

参考

批量给图片文件重命名

给一批文件重命名

问题1:使用os.path.join()函数合并路径的时候,只显示后面的。
原因:使用os.path.join(r’D:\datasets\new_name’, “/1000” + str(i) + “.jpg”)

os.path.join()函数中可以传入多个路径: 会从第一个以”/”开头的参数开始拼接,之前的参数全部丢弃。
以上一种情况为先。在上一种情况确保情况下,若出现”./”开头的参数,会从”./”开头的参数的上一个参数开始拼接

注意下面代码中的os.rename(old_name, new_name)是对原始文件直接操作,会导致原始文件消失,如果要保留原始文件,使用shutil.copy(old_name, new_name)。

# 日期:  2023/4/22 11:47
import osroot_path = r'D:\datasets\1osr_original_img'if os.path.exists(root_path):i = 1for filename in os.listdir(root_path):# 把图像改名old_name = os.path.join(root_path, filename)# 保证图片文件名称位数一致lens = 5 - len(str(i))new_name = os.path.join(root_path, "1" + "0"*lens + str(i) + ".jpg")  # 100001# 当文件不存在的时候创建,否则会报错:当文件已存在时,无法创建该文件。if not os.path.exists(new_name):os.rename(old_name, new_name)i += 1# 记录修改过程filelist = []if old_name != new_name:filelist.append('Old: ' + old_name)filelist.append('New: ' + new_name)f = open("rename_log.txt", "a")for file in filelist:f.write(file + '\n')f.close()print('OK')
else:print("路径不存在!")

注意:使用该代码处理文件会删除原来的图片,只保存新的图片。
操作有风险,所以可以记录修改过程。

参考

把一批文件顺序打乱重命名

# 日期:  2023/4/22 11:47
import os
import randomroot_path = './crop_images/origin_imgs1'
save_path = './crop_images/origin_imgs'if os.path.exists(root_path):lst = []for filename in os.listdir(root_path):i = random.randint(1, 242)while i in lst:i = random.randint(1, 242)lst.append(i)# 把图像改名old_name = os.path.join(root_path, filename)# 保证图片文件名称位数一致lens = 5 - len(str(i))new_name = os.path.join(save_path, "1" + "0" * (lens - 1) + str(i) + ".jpg")  # 100001# 当文件不存在的时候创建,否则会报错:当文件已存在时,无法创建该文件。if os.path.exists(new_name):print('文件名已存在。')else:os.rename(old_name, new_name)# i += 1# 记录修改过程filelist = []if old_name != new_name:filelist.append('Old: ' + old_name)filelist.append('New: ' + new_name)f = open("rename_log1.txt", "a")for file in filelist:f.write(file + '\n')f.close()print('OK')
else:print("路径不存在!")

图像旋转/翻转

# 日期:  2023/4/21 20:02
import cv2
import osimport numpy as np
from PIL import Imageroot_path = r'D:\datasets\osr_original_img'for filename in os.listdir(root_path):img_path = os.path.join(root_path, filename)angle = 270# 旋转方式# 1times = angle // 90img = cv2.imread(img_path)  # 生成的是numpy.ndarray,为ndarray多维数组类型,(H,W,C)img = np.rot90(img, k=times, axes=(0, 1))  # 对图像矩阵顺时针旋转90度,得到的像素与原来不同,变为H,W,与手机和电脑里对照片的旋转功能相同,如果想要顺时针,k设置为负数# 旋转后的图片的保存路径if angle == 90:new_name = filename.split('.')[0] + '_090.jpg'else:new_name = filename.split('.')[0] + '_{}.jpg'.format(angle)save_path = '../datasets/np rot{}/'.format(angle) + new_name# 使用cv2库保存图片,直接对矩阵保存就行cv2.imwrite(save_path, img)  # 保存旋转后的图像# # 2# img = Image.open(img_path)  # 生成的是PIL.JpegImagePlugin.JpegImageFile,(W,H)# img = img.transpose(Image.ROTATE_180)  # 引用固定的常量值,得到的像素与原来不同,变为H,W,与手机和电脑里对照片的旋转功能相同# 3# img = Image.open(img_path)  # 生成的是PIL.JpegImagePlugin.JpegImageFile,(W,H)# img = img.rotate(angle)  # 自定义旋转度数,得到的图片的像素与原来一样,都是W,H。逆时针旋转,如果需要顺时针加负号# # 旋转后的图片的保存路径# if angle == 90:#     new_name = filename.split('.')[0] + '_090.jpg'# else:#     new_name = filename.split('.')[0] + '_{}.jpg'.format(angle)## save_path = '../datasets/rotate{}/'.format(angle) + new_name# # 使用Image库保存图片# img.save(save_path)

关于图像的旋转,有时候容易出现理解偏差,rotate是旋转,Transpose是变换位置,本文用翻转来指代。这两个功能的说明如下:

img.rotate(90) 是旋转90度, 这里要注意,只是对于图像内容进行旋转,图片文件本身(或者可以理解为画布)并不会旋转。
Image.Transpose.ROTATE_90,是翻转90度,通过执行这条语句,整个画布才会翻转。

在使用NumPy库中的np.rot90函数时,第二个参数k表示旋转的次数,如果k是正整数,则将数组旋转k次,如果k是负整数,则将数组逆时针旋转abs(k)次。
而第三个参数axes表示要交换的轴。默认情况下,将交换前两个轴。例如,对于二维数组,将交换第一维和第二维。在这种情况下,不需要指定第三个参数。
但是,当处理的数组不是二维数组时,就需要指定axes参数。在这种情况下,axes应该是一个长度为2的元组,用于指定要交换的轴。例如,在三维数组中,可以将第一维和第二维交换,而第三维保持不变,可以使用axes=(1,0)。
在代码中,-1作为axes参数的值。在这种情况下,-1表示最后一个轴。因此,np.rot90函数将沿着数组的最后一个轴旋转。这相当于在二维数组中,将第一维和第二维交换。

参考1
参考2
参考3
参考4

将图像和对应的xml标签文件都翻转

注释部分是垂直翻转,下面的是水平翻转。

flip_bbox_horizontal 函数的作用是对 XML 标注文件中的矩形框坐标进行水平翻转,并将修改后的标注文件保存到指定路径下。
具体而言,该函数首先使用 ET.parse 函数对传入的 XML 文件进行解析,并获取 XML 文件的根节点。然后,它遍历根节点下的所有 object 节点,对每个节点下的 bndbox 子节点表示的矩形框坐标进行水平翻转。在水平翻转过程中,函数首先获取矩形框的左右两个边界坐标 xmin 和 xmax,然后将 xmin 修改为原图像宽度减去 xmax,xmax 修改为原图像宽度减去 xmin,从而实现矩形框坐标的水平翻转。
最后,函数使用 ET.ElementTree.write 方法将修改后的 XML 标注文件保存到指定路径下。
需要注意的是,该函数的参数 image_width 是用于表示图像宽度的参数,它用于计算矩形框坐标的水平翻转。因此,在调用该函数时,需要将对应图像的宽度传入该参数中。

import os
import xml.etree.ElementTree as ET
from PIL import Image# def flip_image_vertical(image_path, save_path, output_dir):
#     image = Image.open(image_path)
#     flipped_image = image.transpose(Image.FLIP_TOP_BOTTOM)
#     save_dir = os.path.join(output_dir, os.path.relpath(os.path.dirname(image_path), os.path.dirname(input_image_dir)))
#     if not os.path.exists(save_dir):
#         os.makedirs(save_dir)
#     flipped_image.save(os.path.join(save_dir, os.path.basename(save_path)))
#
#
# def flip_bbox_vertical(xml_path, save_path, image_height, output_dir):
#     tree = ET.parse(xml_path)
#     root = tree.getroot()
#     for obj in root.iter('object'):
#         bbox = obj.find('bndbox')
#         ymin = int(bbox.find('ymin').text)
#         ymax = int(bbox.find('ymax').text)
#         bbox.find('ymin').text = str(image_height - ymax)
#         bbox.find('ymax').text = str(image_height - ymin)
#     save_dir = os.path.join(output_dir, os.path.relpath(os.path.dirname(xml_path), os.path.dirname(input_xml_dir)))
#     if not os.path.exists(save_dir):
#         os.makedirs(save_dir)
#     tree.write(os.path.join(save_dir, os.path.basename(save_path)))
#
#
# def main(input_image_dir, input_xml_dir, output_image_dir, output_xml_dir):
#     for root, dirs, files in os.walk(input_image_dir):
#         for file in files:
#             if file.endswith('.jpg'):
#                 # 竖直翻转图像
#                 image_path = os.path.join(root, file)
#                 flipped_image_path = os.path.join(os.path.relpath(root, input_image_dir),
#                                                   file.split('.')[0] + '_vertical_flipped.jpg')
#                 flip_image_vertical(image_path, flipped_image_path, output_image_dir)
#
#                 # 修改XML文件中矩形框坐标
#                 xml_path = os.path.join(input_xml_dir, file.split('.')[0] + '.xml')
#                 flipped_xml_path = os.path.join(os.path.relpath(root, input_image_dir),
#                                                 file.split('.')[0] + '_vertical_flipped.xml')
#                 flip_bbox_vertical(xml_path, flipped_xml_path, Image.open(image_path).size[1], output_xml_dir)
#
#
# if __name__ == '__main__':
#     input_image_dir = 'img/image'
#     input_xml_dir = 'img/label'
#     output_image_dir = 'img_vertical_flip/image'
#     output_xml_dir = 'img_vertical_flip/label'
#     if not os.path.exists(output_image_dir):
#         os.makedirs(output_image_dir)
#     if not os.path.exists(output_xml_dir):
#         os.makedirs(output_xml_dir)
#     main(input_image_dir, input_xml_dir, output_image_dir, output_xml_dir)def flip_image_horizontal(image_path, save_path):image = Image.open(image_path)flipped_image = image.transpose(Image.FLIP_LEFT_RIGHT)flipped_image.save(save_path)def flip_bbox_horizontal(xml_path, save_path, image_width):tree = ET.parse(xml_path)root = tree.getroot()for obj in root.iter('object'):bbox = obj.find('bndbox')xmin = int(bbox.find('xmin').text)xmax = int(bbox.find('xmax').text)bbox.find('xmin').text = str(image_width - xmax)bbox.find('xmax').text = str(image_width - xmin)tree.write(save_path)def main(image_dir, xml_dir, output_dir):for root, dirs, files in os.walk(image_dir):for file in files:if file.endswith('.jpg'):# 水平翻转图像image_path = os.path.join(image_dir, file)flipped_image_path = os.path.join(output_dir, file.split('.')[0] + '_flipped.jpg')flip_image_horizontal(image_path, flipped_image_path)# 修改XML文件中矩形框坐标xml_path = os.path.join(xml_dir, file.split('.')[0] + '.xml')flipped_xml_path = os.path.join(output_dir, file.split('.')[0] + '_flipped.xml')flip_bbox_horizontal(xml_path, flipped_xml_path, Image.open(image_path).size[0])if __name__ == '__main__':image_dir = 'img/image'xml_dir = 'img/label'output_dir = 'img_flip/output_dir'if not os.path.exists(output_dir):os.makedirs(output_dir)main(image_dir, xml_dir, output_dir)

将目标所在区域裁剪出来

最后发现方法三好用!

方法一

将玻璃片所在区域裁剪出来。

# 日期:  2023/4/22 14:34
import cv2
import numpy as np# 读取图片
img_path = r'D:\datasets\osr_original_img\100001.jpg'
img = cv2.imread(img_path)# 灰度化处理
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# 边缘检测
edges = cv2.Canny(gray, 100, 200)# 轮廓检测
contours, hierarchy = cv2.findContours(edges, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)# 找到矩形轮廓
rect = None
for cnt in contours:approx = cv2.approxPolyDP(cnt, 0.01*cv2.arcLength(cnt, True), True)if len(approx) == 4:rect = approxbreak# 裁剪矩形区域
if rect is not None:rect = rect.reshape(-1, 2)x, y, w, h = cv2.boundingRect(rect)roi = img[y:y+h, x:x+w]cv2.imwrite('D:/your_cropped_image_path.jpg', roi)

代码中的步骤如下:

  1. 读取照片并转换为灰度图像。
  2. 对灰度图像进行边缘检测。
  3. 通过轮廓检测找到接近矩形的轮廓。
  4. 利用矩形轮廓的边界框(bounding box)裁剪出矩形区域。
  5. 将裁剪出的区域保存为新的图片。
    上述代码处理一些图片的时候会使输出全部为黑色。

方法二:

import cv2
import numpy as npimage = cv2.imread(r'D:\datasets\osr_original_img\100018.jpg')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)gradX = cv2.Sobel(gray, ddepth=cv2.CV_32F, dx=1, dy=0, ksize=-1)
gradY = cv2.Sobel(gray, ddepth=cv2.CV_32F, dx=0, dy=1, ksize=-1)# subtract the y-gradient from the x-gradient
gradient = cv2.subtract(gradX, gradY)
gradient = cv2.convertScaleAbs(gradient)# blur and threshold the image
blurred = cv2.blur(gradient, (9, 9))
(_, thresh) = cv2.threshold(blurred, 90, 255, cv2.THRESH_BINARY)kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (25, 25))
closed = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)# perform a series of erosions and dilations
closed = cv2.erode(closed, None, iterations=4)
closed = cv2.dilate(closed, None, iterations=4)(cnts, _) = cv2.findContours(closed.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
c = sorted(cnts, key=cv2.contourArea, reverse=True)[0]# compute the rotated bounding box of the largest contour
rect = cv2.minAreaRect(c)
box = np.int0(cv2.boxPoints(rect))# draw a bounding box arounded the detected barcode and display the image
# cv2.drawContours(image, [box], -1, (255, 255, 255), 2)
cv2.imshow("Image", image)
cv2.imwrite("contoursImage2.jpg", image)
cv2.waitKey(0)Xs = [i[0] for i in box]
Ys = [i[1] for i in box]
x1 = min(Xs)
x2 = max(Xs)
y1 = min(Ys)
y2 = max(Ys)
hight = y2 - y1
width = x2 - x1
cropImg = image[y1:y1+hight, x1:x1+width]cv2.imwrite('D:/your_warped_image_path18.jpg', cropImg)

参考

方法三

import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import math# 图像灰度延展、直方图均衡化file_root = "./osr_original_img"  # 当前文件夹下的所有图片
file_list = os.listdir(file_root)
save_out = "./crop_images/origin_imgs1"  # 保存图片的文件夹名称
for img_name in file_list:img_path = file_root + "/" + img_nameoriginal_image = cv2.imread(img_path, -1)image = original_image.copy()gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)blurred = cv2.GaussianBlur(gray, (3, 3), 0)canny = cv2.Canny(blurred, 120, 255, 1)kernel = np.ones((9, 9), np.uint8)result = cv2.dilate(canny, kernel)# Find contours in the imagecnts = cv2.findContours(result.copy(), cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)cnts = cnts[0] if len(cnts) == 2 else cnts[1]# Obtain area for each contourcontour_sizes = [(cv2.arcLength(contour, True), contour) for contour in cnts]# Find maximum contour and crop for ROI sectionif len(contour_sizes) > 0:largest_contour = max(contour_sizes, key=lambda x: x[0])[1]# cv2.drawContours(image, largest_contour, -1, (0, 255, 0), 10)x, y, w, h = cv2.boundingRect(largest_contour)# cv2.rectangle(image, (x, y), (x + w, y + h), (255, 0, 0), 5)ROI = original_image[y-100:y + h + 100, x-100:x + w + 100]out_name = img_name.split('.')[0]save_path = save_out + "/" + out_name + '.jpg'cv2.imwrite(save_path, ROI)

裁剪并纠偏

将玻璃片所在区域裁剪出来。并且把裁剪出来的图片纠偏,因为工业相机拍照的时候会产生畸变。

要将拍摄的图像进行纠偏,使矩形玻璃片在图像中成为矩形,可以使用OpenCV库中的透视变换(perspective transformation)来实现。

下面代码的问题是裁剪纠偏之后的图片相比于原图发生了旋转,像是经过了水平镜像,不知道是否对所有图片都是这样。

import cv2
import numpy as np# 读取图片
img = cv2.imread(r'D:\datasets\osr_original_img\100002.jpg')# 灰度化处理
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# 边缘检测
edges = cv2.Canny(gray, 100, 200)# 轮廓检测
contours, hierarchy = cv2.findContours(edges, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)# 找到矩形轮廓
rect = None
for cnt in contours:approx = cv2.approxPolyDP(cnt, 0.01*cv2.arcLength(cnt, True), True)if len(approx) == 4:rect = approxbreak# 纠偏图像
if rect is not None:rect = rect.reshape(-1, 2)rect = rect.astype(np.float32)(tl, tr, br, bl) = rectw1 = np.sqrt((tl[0]-tr[0])**2 + (tl[1]-tr[1])**2)w2 = np.sqrt((bl[0]-br[0])**2 + (bl[1]-br[1])**2)h1 = np.sqrt((tl[0]-bl[0])**2 + (tl[1]-bl[1])**2)h2 = np.sqrt((tr[0]-br[0])**2 + (tr[1]-br[1])**2)maxWidth = max(int(w1), int(w2))maxHeight = max(int(h1), int(h2))dst = np.array([[0, 0], [maxWidth-1, 0], [maxWidth-1, maxHeight-1], [0, maxHeight-1]], dtype=np.float32)M = cv2.getPerspectiveTransform(rect, dst)warped = cv2.warpPerspective(img, M, (maxWidth, maxHeight))cv2.imwrite('D:/your_warped_image_path2.jpg', warped)

代码中的步骤如下:

1.读取照片并转换为灰度图像。
2.对灰度图像进行边缘检测。
3.通过轮廓检测找到接近矩形的轮廓。
4.利用矩形轮廓的边界框裁剪出矩形区域。
5.计算矩形区域的四个顶点在变换后的图像中的位置。
6.利用透视变换(Perspective Transformation)将矩形区域变换为矩形。
7.将变换后的图像保存为新的图片。

在代码中,首先找到了接近矩形的轮廓,并通过轮廓的边界框计算了矩形区域的四个顶点在变换后的图像中的位置。然后,利用cv2.getPerspectiveTransform()函数求得透视变换矩阵M,并使用cv2.warpPerspective()函数将图像进行透视变换。变换后的图像将会是一个矩形,其中玻璃片也将成为一个矩形。

图像扩增方法合集(对单张图片)

注意修改读取和保存图片的路径,并根据需要修改其中的参数。

from PIL import Image, ImageEnhance, ImageFilter, ImageDraw
import randomimg_path = 'crop_images/0427origin_imgs/100272.jpg'
num = 100272image = Image.open(img_path)  # 打开图片文件# 旋转30度rotated_image = image.rotate(30)  # 将图片旋转30度
rotated_image.save("crop_images/rotated_image_{}.jpg".format(num))  # 保存旋转后的图片文件# 水平翻转flipped_image = image.transpose(Image.FLIP_LEFT_RIGHT)  # 将图片水平翻转
flipped_image.save("crop_images/flipped_image_{}.jpg".format(num))  # 保存翻转后的图片文件# 随机裁剪width, height = image.size  # 获取图片的宽和高
crop_width, crop_height = 500, 500  # 设定裁剪后的图片大小
left = random.randint(0, width - crop_width)  # 随机生成左上角横坐标
upper = random.randint(0, height - crop_height)  # 随机生成左上角纵坐标
right = left + crop_width  # 计算右下角横坐标
lower = upper + crop_height  # 计算右下角纵坐标
cropped_image = image.crop((left, upper, right, lower))  # 裁剪图片
cropped_image.save("crop_images/cropped_image_{}.jpg".format(num))  # 保存裁剪后的图片文件# 平移offset = (50, 50)  # 定义平移量
trans_image = image.transform(image.size, Image.AFFINE, (1, 0, offset[0], 0, 1, offset[1]))  # 对图片进行平移
trans_image.save("trans_image.jpg")  # 保存平移后的图片文件# 对比度增强contrast_enhancer = ImageEnhance.Contrast(image)  # 创建对比度增强器
enhanced_image = contrast_enhancer.enhance(1.5)  # 对图片进行对比度增强
enhanced_image.save("contrast_enhanced_image.jpg")  # 保存对比度增强后的图片文件# 亮度增强brightness_enhancer = ImageEnhance.Brightness(image)  # 创建亮度增强器
enhanced_image = brightness_enhancer.enhance(1.5)  # 对图片进行亮度增强
enhanced_image.save("brightness_enhanced_image.jpg")  # 保存亮度增强后的图片文件# 颜色转换converted_image = image.copy()  # 创建图片副本
r, g, b = converted_image.split()  # 分离图片的RGB通道
r = r.point(lambda i: i + 50)  # 对R通道进行颜色转换
g = g.point(lambda i: i - 30)  # 对G通道进行颜色转换
b = b.point(lambda i: i - 20)  # 对B通道进行颜色转换
converted_image = Image.merge("RGB", (r, g, b))  # 合并三个通道重构图片
converted_image.save("converted_image.jpg")  # 保存颜色转换后的图片文件# 转换为灰度图converted_image = image.convert("L")  # 将图片转换为灰度图
converted_image.save("gray_image.jpg")  # 保存灰度图# 模糊blurred_image = image.filter(ImageFilter.GaussianBlur(radius=2))  # 对图片进行高斯模糊
blurred_image.save("blurred_image.jpg")  # 保存模糊后的图片文件# 锐化sharpened_image = image.filter(ImageFilter.SHARPEN)  # 对图片进行锐化
sharpened_image.save("sharpened_image.jpg")  # 保存锐化后的图片文件# 添加噪声draw = ImageDraw.Draw(image)  # 创建绘制对象
width, height = image.size  # 获取图片的宽和高
for x in range(width):for y in range(height):draw.point((x, y), fill=(random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)))  # 为每个像素点添加随机噪声
image.save("noisy_image.jpg")  # 保存添加噪声后的图片文件

深度学习中基于python的预处理和图像扩增方法相关推荐

  1. 《深度学习入门——基于Python的理论与实现》笔记

    PS:写这篇博客主要是记录下自己认为重要的部分以及阅读中遇到的些问题,加深自己的印象. 附上电子书及源代码: 链接:https://pan.baidu.com/s/1f2VFcnXSSK-u3wuvg ...

  2. 《深度学习入门-基于Python的理论与实现》学习笔记1

    <深度学习入门-基于Python的理论与实现>学习笔记1 第一章Python入门 Python是一个简单.易读.易记的编程语言,可以用类似于英语的语法进行编写程序,可读性高,且能写出高性能 ...

  3. 《深度学习入门--基于python的理论与实现》——斋藤康毅读书笔记

    <深度学习入门--基于python的理论与实现>读书笔记(第二章) 写在前面 第二章:感知机 2.1感知机是什么 2.2简单的逻辑电路 2.2.1与门(and gate) 2.2.2与非门 ...

  4. 深度学习入门 基于Python的理论与实现

    作者:斋藤康毅 出版社:人民邮电出版社 品牌:iTuring 出版时间:2018-07-01 深度学习入门 基于Python的理论与实现

  5. 深度学习入门-基于Python的理论入门与实现源代码加mnist数据集下载推荐

    深度学习入门-基于Python的理论入门与实现源代码加mnist数据集下载推荐 书籍封面 1-图灵网站下载 书里也说了,可以图灵网站下载https://www.ituring.com.cn/book/ ...

  6. python从入门到精通 邮电出版社_《人民邮电出版社Python深度学习入门:基于PYTHON的理论与实现》【价格 目录 书评 正版】_中国图书网...

    译者序 xiii 前言 xv 第 1 章 Python入门 1 1.1 Python是什么 1 1.2 Python的安装 2 1.2.1 Python版本 2 1.2.2 使用的外部库 2 1.2. ...

  7. 深度学习入门基于Python的理论与实现_第一章_Python入门(原创笔记)

    前言 此书使用Python作为编程语言,尽可能地少使用外部库,从零开始实现深度学习的程序. 此书从简单的机器学习问题开始,最终实现一个能高精度地识别图像的系统. 此书以图像识别为主题,主要学习使用深度 ...

  8. 《深度学习入门——基于Python的理论与实现》斋藤康毅学习笔记(二)

    第二章 感知机 1逻辑门 错误:python 出现的异常 inconsistent use of tabs and spaces in indentation 意思是:在缩进中不一致地使用制表符和空格 ...

  9. 《深度学习入门 基于Python的理论与实现》书中代码笔记

    源码笔记[仅为个人笔记记录] 第三章 sigmoid函数 # coding: utf-8 import numpy as np import matplotlib.pylab as pltdef si ...

  10. 《深度学习入门——基于Python的理论与实现》斋藤康毅学习笔记(一)

    第一章 (只将自己有疑惑并得到解决的学习内容作以下笔记) 1.python解释器 1.1数组 错误:a[ : -1] 不是获取所有元素 修改:a[ : -1]表示获取从第一个元素到最后一个元素之间的元 ...

最新文章

  1. Android RecyclerView(和SnapHelper) 实现类似ViewPager的效果
  2. 剑指offer——二进制中1的个数(c++)
  3. 02(c)多元无约束优化问题-牛顿法
  4. 从数据角度看,每家公司只有2种角色:看看你更适合哪一种?
  5. Java集合---面试题
  6. 安徽大学计算机科学与技术学院刘峰,刘峰
  7. JDK1.8源码(十一)——java.util.TreeMap类
  8. 使用PHP来简单的创建一个RPC服务
  9. C# 搭建一个简单的WebApi项目
  10. asp big5 gb2312 转 Unicode
  11. iphone,ipad 尺寸,iphone常用控件尺寸
  12. android系统级别应用开发要点
  13. 获取docker容器里面的root权限
  14. 去除IE自带的输入框清除按钮
  15. Mac上如何降级系统?Mac系统降级图文教程
  16. java-net-php-python-jsp房屋出租网站-视频演示计算机毕业设计程序
  17. grpc-gateway
  18. ultraiso命令行使用
  19. 谁的青春不迷茫 致在下小苏 20多岁的人,今天就这样了,明天只会更好,不会更差了吧 ! 也是致自己
  20. 毕设前期准备——调制信号+聚类+信号预处理+类内类间识别+星座图模块

热门文章

  1. 华为防火墙-5-NAT
  2. 三甲医院手术麻醉系统源码, C# .net 桌面软件 C/S版源码
  3. php实现排序功能(提供全部)
  4. c语言对变量作强制定义理由,C语言中要求对变量作强制定义的主要理由是()。...
  5. 大白话说三次握手、四次挥手
  6. stm32学习日记--USART
  7. 蓝桥杯算法训练-士兵杀敌(Java 和 C++ 代码)
  8. 数通笔记IP.4-BGP
  9. jupyter notebook无法打开的问题
  10. 大数据分析案例-基于决策树算法预测ICU患者是否需要插管