{ "cells": [ { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "四生乐句付仗斥令仔乎白仙甩他瓜们用丘仪失丛代印册匆禾\n" ] } ], "source": [ "from captcha.image import ImageCaptcha\n", "import matplotlib.pyplot as plt\n", "import numpy as np\n", "import random\n", "import glob\n", "from pylab import mpl\n", "mpl.rcParams['font.sans-serif'] = ['SimHei'] #中文显示问题\n", "\n", "%matplotlib inline\n", "%config InlineBackend.figure_format = 'retina'\n", "\n", "import string\n", "# characters = string.digits + string.ascii_uppercase # 验证码字符集合数字+英文\n", "characters = '四生乐句付仗斥令仔乎白仙甩他瓜们用丘仪失丛代印册匆禾' # 中文字符集合\n", "print(characters)\n", "\n", "width, height, n_len, n_class = 100, 50, 6, len(characters) + 1 #图片宽、高,验证码最大长度,分类类别:字符集+1个空值" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [], "source": [ " # 防止 tensorflow 占用所有显存\n", "import tensorflow as tf\n", "import tensorflow.keras.backend as K\n", "\n", "config = tf.ConfigProto()\n", "config.gpu_options.allow_growth=True #True \n", "sess = tf.Session(config=config)\n", "K.set_session(sess)\n" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "# 定义 CTC Loss\n", "import tensorflow.keras.backend as K\n", "\n", "def ctc_lambda_func(args):\n", " '''\n", " 定义ctc损失函数\n", " 参数:y_pred:预测值,labels:标签,input_length:lstm tiemstep,label_length:标签长度\n", " ''' \n", " y_pred, labels, input_length, label_length = args\n", " return K.ctc_batch_cost(labels, y_pred, input_length, label_length)" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "# 定义网络\n", "from tensorflow.keras.models import *\n", "from tensorflow.keras.layers import *\n", "\n", "input_tensor = Input((height, width, 3))\n", "x = input_tensor\n", "\n", "for i, n_cnn in enumerate([2, 2, 2, 2]): \n", " for j in range(n_cnn):\n", " x = Conv2D(32*2**min(i, 3), kernel_size=3, padding='same', kernel_initializer='he_uniform')(x) # 32*2**min(i, 3)\n", " x = BatchNormalization()(x)\n", " x = Activation('relu')(x)\n", " x = MaxPooling2D(2 if i < 3 else (2, 1))(x)\n", "\n", "x = Permute((2, 1, 3))(x)\n", "x = TimeDistributed(Flatten())(x)\n", "\n", "rnn_size = 64 # 128\n", "# x = Bidirectional(CuDNNGRU(rnn_size, return_sequences=True))(x)\n", "# x = Bidirectional(CuDNNGRU(rnn_size, return_sequences=True))(x)\n", "x = Bidirectional(GRU(rnn_size, return_sequences=True))(x)\n", "x = Bidirectional(GRU(rnn_size, return_sequences=True))(x)\n", "x = Dense(n_class, activation='softmax')(x)\n", "\n", "base_model = Model(inputs=input_tensor, outputs=x)" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "labels = Input(name='the_labels', shape=[n_len], dtype='float32')\n", "input_length = Input(name='input_length', shape=[1], dtype='int64')\n", "label_length = Input(name='label_length', shape=[1], dtype='int64')\n", "loss_out = Lambda(ctc_lambda_func, output_shape=(1,), name='ctc')([x, labels, input_length, label_length])\n", "\n", "model = Model(inputs=[input_tensor, labels, input_length, label_length], outputs=loss_out)" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "# # 网络结构可视化\n", "# from tensorflow.keras.utils import plot_model\n", "# from IPython.display import Image\n", "\n", "# plot_model(model, to_file='ctc.png', show_shapes=True)\n", "# Image('ctc.png')\n" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "# base_model.summary()" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "/home/python/anaconda3/envs/dl_nlp/lib/python3.5/site-packages/matplotlib/font_manager.py:1241: UserWarning: findfont: Font family ['sans-serif'] not found. Falling back to DejaVu Sans.\n", " (prop.get_family(), self.defaultFamily[fontext]))\n" ] }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "image/png": { "height": 279, "width": 1138 }, "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "from PIL import Image, ImageFont, ImageDraw\n", "\n", "def random_color(start, end, opacity=None):\n", " '''\n", " 随机颜色函数,返回指定范围随机颜色值\n", " 参数:start:颜色最低值,end:颜色最高值\n", " '''\n", " red = random.randint(start, end)\n", " green = random.randint(start, end)\n", " blue = random.randint(start, end)\n", " if opacity is None:\n", " return (red, green, blue)\n", " return (red, green, blue, opacity)\n", "def random_xy(width,height): \n", " '''\n", " 随机位置函数,返回指定范围随机位置坐标\n", " 参数:width:图片宽,height:图片高\n", " '''\n", " x = random.randint(0, width)\n", " y = random.randint(0, height)\n", " return x, y\n", "\n", "table = []\n", "for i in range( 256 ):\n", " table.append( i * 1.97 )\n", " \n", "def create_captcha_image(chars, background, width=100, height=25):\n", " '''\n", " 生成验证码图片\n", " chars:要生成的字符串\n", " background:背景颜色\n", " '''\n", " image = Image.new('RGB', (width, height), color=background)\n", " draw = ImageDraw.Draw(image)\n", " def get_char_img(char,font,color,angle):\n", " '''\n", " 生成单个字符图片,随机颜色加随机旋转\n", " \n", " '''\n", " w, h = draw.textsize(char, font=font)\n", " im = Image.new('RGBA',(w,h), color=background)\n", " ImageDraw.Draw(im).text((0,0), char, font=font, fill=color)\n", " im = im.crop(im.getbbox())\n", " rot = im.rotate(angle,Image.BILINEAR,expand=1)\n", " bg = Image.new('RGBA',rot.size,background)\n", " im = Image.composite(rot, bg, rot)\n", " return im\n", " w_all = 0\n", " im_list = []\n", " w_list = []\n", " for c in chars:\n", " fonts = ['/usr/share/fonts/WindowsFonts/fonts/STXINGKA.TTF','/usr/share/fonts/WindowsFonts/fonts/simhei.ttf']\n", " font = ImageFont.truetype(font=random.choice(fonts), size=random.randint(18,20))\n", " char_img = get_char_img(char=c, font=font, color=random_color(0,130), angle=random.randint(0,0))\n", " w, h = char_img.size\n", " w_all += random.randint(0,5) \n", " w_list.append(w_all)\n", " im_list.append(char_img)\n", "# image.paste(char_img, (w_all,random.randint(0,image.size[1]-h)))\n", " w_all += w\n", " if w_all > width:\n", " image = Image.new('RGB', (w_all, height), color=background)\n", "\n", " for i in range(len(w_list)):\n", " image.paste(im_list[i], (w_list[i],random.randint(0,height-im_list[i].size[1])))\n", " return image.resize((width, height))\n", "\n", "def generate_image(random_str, width=100, height=25):\n", " '''\n", " 随机生成验证码,从四种字体随机抽取一种生成文字,加随机线干扰和点干扰\n", " 参数:random_str:要生成验证码的文字\n", " 返回:验证码图片\n", " ''' \n", "# image = Image.new(mode='RGB', size=(width, height), color=(255,255,255))\n", " fonts = ['/usr/share/fonts/WindowsFonts/fonts/simsunb.ttf']\n", "# fonts = ['/usr/share/fonts/WindowsFonts/fonts/ariali.ttf', '/usr/share/fonts/WindowsFonts/fonts/simhei.ttf',\n", "# '/usr/share/fonts/WindowsFonts/fonts/simsunb.ttf', '/usr/share/fonts/WindowsFonts/fonts/calibri.ttf']\n", " font = ImageFont.truetype(font=random.choice(fonts), size=20)\n", " chars = random_str\n", " color = random_color(120,250)\n", " background = random_color(50,255)\n", " image = create_captcha_image(chars, background)\n", " draw = ImageDraw.Draw(image) \n", "# for _ in range(random.randint(5, 10)):\n", "# draw.line(xy=(random_xy(width,height),random_xy(width,height)),fill=random_color(80, 255))\n", " for _ in range(random.randint(100,150)):\n", " draw.point(xy=(random_xy(width,height)),fill=random_color(20, 250))\n", "# for _ in range(random.randint(50,80)):\n", "# x,y = random_xy(width,height)\n", "# draw.line(xy=(x,y,x+random.randint(-10,15),y+random.randint(-10,15)),fill=random_color(120, 255))\n", " \n", "# draw.text(xy=(random.randint(0,10),random.randint(0,2)),text= random_str, fill=text_fill, font=font)\n", "# len_t = len(random_str)\n", "# for i in range(len_t):\n", "# draw.text(xy=(random.randint(0,2)+i*int(width/len_t),random.randint(1,6)),text= random_str[i], \n", "# fill=random_color(0,180,opacity=80), font=font)\n", " \n", " return image.resize((100,50), Image.BILINEAR)\n", "\n", "img = generate_image('瓜用匆生')\n", "img2 = Image.open('Chinese/1da7be39-2189-11ea-b304-408d5cd36814_瓜用匆生.jpg')\n", "img2 = img2.resize((100,50), Image.BILINEAR)\n", "im = [img, img2]\n", "plt.figure(figsize=(20,10))\n", "for i in range(1,3): \n", " plt.subplot(2,2,i)\n", " plt.imshow(im[i-1])\n", "plt.show()\n", "\n", "# plt.imshow(img)" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [], "source": [ "# 重组验证码\n", "def rebuild_img(path):\n", " '''\n", " 读取本地4-5位验证码图片进行裁剪分割为单个数字,从分割的字符随机抽取n个重组为新图片\n", " 参数:path:图片路径\n", " 返回:重组后图片\n", " '''\n", " label = path.split('_')[-1][:-4]\n", " if label.isalpha() and len(label) > 3:\n", " crop_n = len(label) \n", " img = Image.open(path)\n", " w, h = img.size\n", " fig_size = int(w/crop_n)\n", " fig_list = []\n", " new_label = []\n", " if crop_n == 4:\n", " for i in range(crop_n):\n", " fig_list.append(img.crop((i*fig_size+2, 2, (i+1)*fig_size-2, h-2 )))\n", " for i in range(crop_n):\n", " idx = random.randint(0,crop_n-1) # 修改为打乱顺序\n", " img.paste(fig_list[idx], (i*fig_size+2, 2, (i+1)*fig_size-2, h-2 ))\n", " new_label.append(label[idx])\n", " elif crop_n == 5: \n", " for i in range(crop_n):\n", " fig_list.append(img.crop((i*fig_size, 0, (i+1)*fig_size, h )))\n", " for i in range(crop_n):\n", " idx = random.randint(0,crop_n-1)\n", " img.paste(fig_list[idx], (i*fig_size, 0, (i+1)*fig_size, h ))\n", " new_label.append(label[idx])\n", " \n", " draw = ImageDraw.Draw(img) \n", " for _ in range(random.randint(0,50)): # 在重组的验证码图片上加噪声\n", " draw.point(xy=(random_xy(width,height)),fill=random_color(20, 250))\n", " \n", " return img.resize((100,50), Image.BILINEAR), ''.join(new_label)" ] }, { "cell_type": "code", "execution_count": 78, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Help on module PIL.Image in PIL:\n", "\n", "NAME\n", " PIL.Image\n", "\n", "DESCRIPTION\n", " # The Python Imaging Library.\n", " # $Id$\n", " #\n", " # the Image class wrapper\n", " #\n", " # partial release history:\n", " # 1995-09-09 fl Created\n", " # 1996-03-11 fl PIL release 0.0 (proof of concept)\n", " # 1996-04-30 fl PIL release 0.1b1\n", " # 1999-07-28 fl PIL release 1.0 final\n", " # 2000-06-07 fl PIL release 1.1\n", " # 2000-10-20 fl PIL release 1.1.1\n", " # 2001-05-07 fl PIL release 1.1.2\n", " # 2002-03-15 fl PIL release 1.1.3\n", " # 2003-05-10 fl PIL release 1.1.4\n", " # 2005-03-28 fl PIL release 1.1.5\n", " # 2006-12-02 fl PIL release 1.1.6\n", " # 2009-11-15 fl PIL release 1.1.7\n", " #\n", " # Copyright (c) 1997-2009 by Secret Labs AB. All rights reserved.\n", " # Copyright (c) 1995-2009 by Fredrik Lundh.\n", " #\n", " # See the README file for information on usage and redistribution.\n", " #\n", "\n", "CLASSES\n", " builtins.Exception(builtins.BaseException)\n", " DecompressionBombError\n", " builtins.RuntimeWarning(builtins.Warning)\n", " DecompressionBombWarning\n", " builtins.object\n", " Image\n", " ImagePointHandler\n", " ImageTransformHandler\n", " \n", " class DecompressionBombError(builtins.Exception)\n", " | Common base class for all non-exit exceptions.\n", " | \n", " | Method resolution order:\n", " | DecompressionBombError\n", " | builtins.Exception\n", " | builtins.BaseException\n", " | builtins.object\n", " | \n", " | Data descriptors defined here:\n", " | \n", " | __weakref__\n", " | list of weak references to the object (if defined)\n", " | \n", " | ----------------------------------------------------------------------\n", " | Methods inherited from builtins.Exception:\n", " | \n", " | __init__(self, /, *args, **kwargs)\n", " | Initialize self. See help(type(self)) for accurate signature.\n", " | \n", " | __new__(*args, **kwargs) from builtins.type\n", " | Create and return a new object. See help(type) for accurate signature.\n", " | \n", " | ----------------------------------------------------------------------\n", " | Methods inherited from builtins.BaseException:\n", " | \n", " | __delattr__(self, name, /)\n", " | Implement delattr(self, name).\n", " | \n", " | __getattribute__(self, name, /)\n", " | Return getattr(self, name).\n", " | \n", " | __reduce__(...)\n", " | helper for pickle\n", " | \n", " | __repr__(self, /)\n", " | Return repr(self).\n", " | \n", " | __setattr__(self, name, value, /)\n", " | Implement setattr(self, name, value).\n", " | \n", " | __setstate__(...)\n", " | \n", " | __str__(self, /)\n", " | Return str(self).\n", " | \n", " | with_traceback(...)\n", " | Exception.with_traceback(tb) --\n", " | set self.__traceback__ to tb and return self.\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data descriptors inherited from builtins.BaseException:\n", " | \n", " | __cause__\n", " | exception cause\n", " | \n", " | __context__\n", " | exception context\n", " | \n", " | __dict__\n", " | \n", " | __suppress_context__\n", " | \n", " | __traceback__\n", " | \n", " | args\n", " \n", " class DecompressionBombWarning(builtins.RuntimeWarning)\n", " | Base class for warnings about dubious runtime behavior.\n", " | \n", " | Method resolution order:\n", " | DecompressionBombWarning\n", " | builtins.RuntimeWarning\n", " | builtins.Warning\n", " | builtins.Exception\n", " | builtins.BaseException\n", " | builtins.object\n", " | \n", " | Data descriptors defined here:\n", " | \n", " | __weakref__\n", " | list of weak references to the object (if defined)\n", " | \n", " | ----------------------------------------------------------------------\n", " | Methods inherited from builtins.RuntimeWarning:\n", " | \n", " | __init__(self, /, *args, **kwargs)\n", " | Initialize self. See help(type(self)) for accurate signature.\n", " | \n", " | __new__(*args, **kwargs) from builtins.type\n", " | Create and return a new object. See help(type) for accurate signature.\n", " | \n", " | ----------------------------------------------------------------------\n", " | Methods inherited from builtins.BaseException:\n", " | \n", " | __delattr__(self, name, /)\n", " | Implement delattr(self, name).\n", " | \n", " | __getattribute__(self, name, /)\n", " | Return getattr(self, name).\n", " | \n", " | __reduce__(...)\n", " | helper for pickle\n", " | \n", " | __repr__(self, /)\n", " | Return repr(self).\n", " | \n", " | __setattr__(self, name, value, /)\n", " | Implement setattr(self, name, value).\n", " | \n", " | __setstate__(...)\n", " | \n", " | __str__(self, /)\n", " | Return str(self).\n", " | \n", " | with_traceback(...)\n", " | Exception.with_traceback(tb) --\n", " | set self.__traceback__ to tb and return self.\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data descriptors inherited from builtins.BaseException:\n", " | \n", " | __cause__\n", " | exception cause\n", " | \n", " | __context__\n", " | exception context\n", " | \n", " | __dict__\n", " | \n", " | __suppress_context__\n", " | \n", " | __traceback__\n", " | \n", " | args\n", " \n", " class Image(builtins.object)\n", " | This class represents an image object. To create\n", " | :py:class:`~PIL.Image.Image` objects, use the appropriate factory\n", " | functions. There's hardly ever any reason to call the Image constructor\n", " | directly.\n", " | \n", " | * :py:func:`~PIL.Image.open`\n", " | * :py:func:`~PIL.Image.new`\n", " | * :py:func:`~PIL.Image.frombytes`\n", " | \n", " | Methods defined here:\n", " | \n", " | __copy__ = copy(self)\n", " | \n", " | __del__(self)\n", " | \n", " | __enter__(self)\n", " | # Context manager support\n", " | \n", " | __eq__(self, other)\n", " | Return self==value.\n", " | \n", " | __exit__(self, *args)\n", " | \n", " | __getstate__(self)\n", " | \n", " | __init__(self)\n", " | Initialize self. See help(type(self)) for accurate signature.\n", " | \n", " | __ne__(self, other)\n", " | Return self!=value.\n", " | \n", " | __repr__(self)\n", " | Return repr(self).\n", " | \n", " | __setstate__(self, state)\n", " | \n", " | alpha_composite(self, im, dest=(0, 0), source=(0, 0))\n", " | 'In-place' analog of Image.alpha_composite. Composites an image\n", " | onto this image.\n", " | \n", " | :param im: image to composite over this one\n", " | :param dest: Optional 2 tuple (left, top) specifying the upper\n", " | left corner in this (destination) image.\n", " | :param source: Optional 2 (left, top) tuple for the upper left\n", " | corner in the overlay source image, or 4 tuple (left, top, right,\n", " | bottom) for the bounds of the source rectangle\n", " | \n", " | Performance Note: Not currently implemented in-place in the core layer.\n", " | \n", " | close(self)\n", " | Closes the file pointer, if possible.\n", " | \n", " | This operation will destroy the image core and release its memory.\n", " | The image data will be unusable afterward.\n", " | \n", " | This function is only required to close images that have not\n", " | had their file read and closed by the\n", " | :py:meth:`~PIL.Image.Image.load` method. See\n", " | :ref:`file-handling` for more information.\n", " | \n", " | convert(self, mode=None, matrix=None, dither=None, palette=0, colors=256)\n", " | Returns a converted copy of this image. For the \"P\" mode, this\n", " | method translates pixels through the palette. If mode is\n", " | omitted, a mode is chosen so that all information in the image\n", " | and the palette can be represented without a palette.\n", " | \n", " | The current version supports all possible conversions between\n", " | \"L\", \"RGB\" and \"CMYK.\" The **matrix** argument only supports \"L\"\n", " | and \"RGB\".\n", " | \n", " | When translating a color image to greyscale (mode \"L\"),\n", " | the library uses the ITU-R 601-2 luma transform::\n", " | \n", " | L = R * 299/1000 + G * 587/1000 + B * 114/1000\n", " | \n", " | The default method of converting a greyscale (\"L\") or \"RGB\"\n", " | image into a bilevel (mode \"1\") image uses Floyd-Steinberg\n", " | dither to approximate the original image luminosity levels. If\n", " | dither is NONE, all values larger than 128 are set to 255 (white),\n", " | all other values to 0 (black). To use other thresholds, use the\n", " | :py:meth:`~PIL.Image.Image.point` method.\n", " | \n", " | When converting from \"RGBA\" to \"P\" without a **matrix** argument,\n", " | this passes the operation to :py:meth:`~PIL.Image.Image.quantize`,\n", " | and **dither** and **palette** are ignored.\n", " | \n", " | :param mode: The requested mode. See: :ref:`concept-modes`.\n", " | :param matrix: An optional conversion matrix. If given, this\n", " | should be 4- or 12-tuple containing floating point values.\n", " | :param dither: Dithering method, used when converting from\n", " | mode \"RGB\" to \"P\" or from \"RGB\" or \"L\" to \"1\".\n", " | Available methods are NONE or FLOYDSTEINBERG (default).\n", " | Note that this is not used when **matrix** is supplied.\n", " | :param palette: Palette to use when converting from mode \"RGB\"\n", " | to \"P\". Available palettes are WEB or ADAPTIVE.\n", " | :param colors: Number of colors to use for the ADAPTIVE palette.\n", " | Defaults to 256.\n", " | :rtype: :py:class:`~PIL.Image.Image`\n", " | :returns: An :py:class:`~PIL.Image.Image` object.\n", " | \n", " | copy(self)\n", " | Copies this image. Use this method if you wish to paste things\n", " | into an image, but still retain the original.\n", " | \n", " | :rtype: :py:class:`~PIL.Image.Image`\n", " | :returns: An :py:class:`~PIL.Image.Image` object.\n", " | \n", " | crop(self, box=None)\n", " | Returns a rectangular region from this image. The box is a\n", " | 4-tuple defining the left, upper, right, and lower pixel\n", " | coordinate. See :ref:`coordinate-system`.\n", " | \n", " | Note: Prior to Pillow 3.4.0, this was a lazy operation.\n", " | \n", " | :param box: The crop rectangle, as a (left, upper, right, lower)-tuple.\n", " | :rtype: :py:class:`~PIL.Image.Image`\n", " | :returns: An :py:class:`~PIL.Image.Image` object.\n", " | \n", " | draft(self, mode, size)\n", " | Configures the image file loader so it returns a version of the\n", " | image that as closely as possible matches the given mode and\n", " | size. For example, you can use this method to convert a color\n", " | JPEG to greyscale while loading it, or to extract a 128x192\n", " | version from a PCD file.\n", " | \n", " | Note that this method modifies the :py:class:`~PIL.Image.Image` object\n", " | in place. If the image has already been loaded, this method has no\n", " | effect.\n", " | \n", " | Note: This method is not implemented for most images. It is\n", " | currently implemented only for JPEG and PCD images.\n", " | \n", " | :param mode: The requested mode.\n", " | :param size: The requested size.\n", " | \n", " | effect_spread(self, distance)\n", " | Randomly spread pixels in an image.\n", " | \n", " | :param distance: Distance to spread pixels.\n", " | \n", " | filter(self, filter)\n", " | Filters this image using the given filter. For a list of\n", " | available filters, see the :py:mod:`~PIL.ImageFilter` module.\n", " | \n", " | :param filter: Filter kernel.\n", " | :returns: An :py:class:`~PIL.Image.Image` object.\n", " | \n", " | frombytes(self, data, decoder_name='raw', *args)\n", " | Loads this image with pixel data from a bytes object.\n", " | \n", " | This method is similar to the :py:func:`~PIL.Image.frombytes` function,\n", " | but loads data into this image instead of creating a new image object.\n", " | \n", " | fromstring(self, *args, **kw)\n", " | \n", " | getbands(self)\n", " | Returns a tuple containing the name of each band in this image.\n", " | For example, **getbands** on an RGB image returns (\"R\", \"G\", \"B\").\n", " | \n", " | :returns: A tuple containing band names.\n", " | :rtype: tuple\n", " | \n", " | getbbox(self)\n", " | Calculates the bounding box of the non-zero regions in the\n", " | image.\n", " | \n", " | :returns: The bounding box is returned as a 4-tuple defining the\n", " | left, upper, right, and lower pixel coordinate. See\n", " | :ref:`coordinate-system`. If the image is completely empty, this\n", " | method returns None.\n", " | \n", " | getchannel(self, channel)\n", " | Returns an image containing a single channel of the source image.\n", " | \n", " | :param channel: What channel to return. Could be index\n", " | (0 for \"R\" channel of \"RGB\") or channel name\n", " | (\"A\" for alpha channel of \"RGBA\").\n", " | :returns: An image in \"L\" mode.\n", " | \n", " | .. versionadded:: 4.3.0\n", " | \n", " | getcolors(self, maxcolors=256)\n", " | Returns a list of colors used in this image.\n", " | \n", " | :param maxcolors: Maximum number of colors. If this number is\n", " | exceeded, this method returns None. The default limit is\n", " | 256 colors.\n", " | :returns: An unsorted list of (count, pixel) values.\n", " | \n", " | getdata(self, band=None)\n", " | Returns the contents of this image as a sequence object\n", " | containing pixel values. The sequence object is flattened, so\n", " | that values for line one follow directly after the values of\n", " | line zero, and so on.\n", " | \n", " | Note that the sequence object returned by this method is an\n", " | internal PIL data type, which only supports certain sequence\n", " | operations. To convert it to an ordinary sequence (e.g. for\n", " | printing), use **list(im.getdata())**.\n", " | \n", " | :param band: What band to return. The default is to return\n", " | all bands. To return a single band, pass in the index\n", " | value (e.g. 0 to get the \"R\" band from an \"RGB\" image).\n", " | :returns: A sequence-like object.\n", " | \n", " | getextrema(self)\n", " | Gets the the minimum and maximum pixel values for each band in\n", " | the image.\n", " | \n", " | :returns: For a single-band image, a 2-tuple containing the\n", " | minimum and maximum pixel value. For a multi-band image,\n", " | a tuple containing one 2-tuple for each band.\n", " | \n", " | getim(self)\n", " | Returns a capsule that points to the internal image memory.\n", " | \n", " | :returns: A capsule object.\n", " | \n", " | getpalette(self)\n", " | Returns the image palette as a list.\n", " | \n", " | :returns: A list of color values [r, g, b, ...], or None if the\n", " | image has no palette.\n", " | \n", " | getpixel(self, xy)\n", " | Returns the pixel value at a given position.\n", " | \n", " | :param xy: The coordinate, given as (x, y). See\n", " | :ref:`coordinate-system`.\n", " | :returns: The pixel value. If the image is a multi-layer image,\n", " | this method returns a tuple.\n", " | \n", " | getprojection(self)\n", " | Get projection to x and y axes\n", " | \n", " | :returns: Two sequences, indicating where there are non-zero\n", " | pixels along the X-axis and the Y-axis, respectively.\n", " | \n", " | histogram(self, mask=None, extrema=None)\n", " | Returns a histogram for the image. The histogram is returned as\n", " | a list of pixel counts, one for each pixel value in the source\n", " | image. If the image has more than one band, the histograms for\n", " | all bands are concatenated (for example, the histogram for an\n", " | \"RGB\" image contains 768 values).\n", " | \n", " | A bilevel image (mode \"1\") is treated as a greyscale (\"L\") image\n", " | by this method.\n", " | \n", " | If a mask is provided, the method returns a histogram for those\n", " | parts of the image where the mask image is non-zero. The mask\n", " | image must have the same size as the image, and be either a\n", " | bi-level image (mode \"1\") or a greyscale image (\"L\").\n", " | \n", " | :param mask: An optional mask.\n", " | :returns: A list containing pixel counts.\n", " | \n", " | load(self)\n", " | Allocates storage for the image and loads the pixel data. In\n", " | normal cases, you don't need to call this method, since the\n", " | Image class automatically loads an opened image when it is\n", " | accessed for the first time.\n", " | \n", " | If the file associated with the image was opened by Pillow, then this\n", " | method will close it. The exception to this is if the image has\n", " | multiple frames, in which case the file will be left open for seek\n", " | operations. See :ref:`file-handling` for more information.\n", " | \n", " | :returns: An image access object.\n", " | :rtype: :ref:`PixelAccess` or :py:class:`PIL.PyAccess`\n", " | \n", " | offset(self, xoffset, yoffset=None)\n", " | \n", " | paste(self, im, box=None, mask=None)\n", " | Pastes another image into this image. The box argument is either\n", " | a 2-tuple giving the upper left corner, a 4-tuple defining the\n", " | left, upper, right, and lower pixel coordinate, or None (same as\n", " | (0, 0)). See :ref:`coordinate-system`. If a 4-tuple is given, the size\n", " | of the pasted image must match the size of the region.\n", " | \n", " | If the modes don't match, the pasted image is converted to the mode of\n", " | this image (see the :py:meth:`~PIL.Image.Image.convert` method for\n", " | details).\n", " | \n", " | Instead of an image, the source can be a integer or tuple\n", " | containing pixel values. The method then fills the region\n", " | with the given color. When creating RGB images, you can\n", " | also use color strings as supported by the ImageColor module.\n", " | \n", " | If a mask is given, this method updates only the regions\n", " | indicated by the mask. You can use either \"1\", \"L\" or \"RGBA\"\n", " | images (in the latter case, the alpha band is used as mask).\n", " | Where the mask is 255, the given image is copied as is. Where\n", " | the mask is 0, the current value is preserved. Intermediate\n", " | values will mix the two images together, including their alpha\n", " | channels if they have them.\n", " | \n", " | See :py:meth:`~PIL.Image.Image.alpha_composite` if you want to\n", " | combine images with respect to their alpha channels.\n", " | \n", " | :param im: Source image or pixel value (integer or tuple).\n", " | :param box: An optional 4-tuple giving the region to paste into.\n", " | If a 2-tuple is used instead, it's treated as the upper left\n", " | corner. If omitted or None, the source is pasted into the\n", " | upper left corner.\n", " | \n", " | If an image is given as the second argument and there is no\n", " | third, the box defaults to (0, 0), and the second argument\n", " | is interpreted as a mask image.\n", " | :param mask: An optional mask image.\n", " | \n", " | point(self, lut, mode=None)\n", " | Maps this image through a lookup table or function.\n", " | \n", " | :param lut: A lookup table, containing 256 (or 65536 if\n", " | self.mode==\"I\" and mode == \"L\") values per band in the\n", " | image. A function can be used instead, it should take a\n", " | single argument. The function is called once for each\n", " | possible pixel value, and the resulting table is applied to\n", " | all bands of the image.\n", " | :param mode: Output mode (default is same as input). In the\n", " | current version, this can only be used if the source image\n", " | has mode \"L\" or \"P\", and the output has mode \"1\" or the\n", " | source image mode is \"I\" and the output mode is \"L\".\n", " | :returns: An :py:class:`~PIL.Image.Image` object.\n", " | \n", " | putalpha(self, alpha)\n", " | Adds or replaces the alpha layer in this image. If the image\n", " | does not have an alpha layer, it's converted to \"LA\" or \"RGBA\".\n", " | The new layer must be either \"L\" or \"1\".\n", " | \n", " | :param alpha: The new alpha layer. This can either be an \"L\" or \"1\"\n", " | image having the same size as this image, or an integer or\n", " | other color value.\n", " | \n", " | putdata(self, data, scale=1.0, offset=0.0)\n", " | Copies pixel data to this image. This method copies data from a\n", " | sequence object into the image, starting at the upper left\n", " | corner (0, 0), and continuing until either the image or the\n", " | sequence ends. The scale and offset values are used to adjust\n", " | the sequence values: **pixel = value*scale + offset**.\n", " | \n", " | :param data: A sequence object.\n", " | :param scale: An optional scale value. The default is 1.0.\n", " | :param offset: An optional offset value. The default is 0.0.\n", " | \n", " | putpalette(self, data, rawmode='RGB')\n", " | Attaches a palette to this image. The image must be a \"P\" or\n", " | \"L\" image, and the palette sequence must contain 768 integer\n", " | values, where each group of three values represent the red,\n", " | green, and blue values for the corresponding pixel\n", " | index. Instead of an integer sequence, you can use an 8-bit\n", " | string.\n", " | \n", " | :param data: A palette sequence (either a list or a string).\n", " | :param rawmode: The raw mode of the palette.\n", " | \n", " | putpixel(self, xy, value)\n", " | Modifies the pixel at the given position. The color is given as\n", " | a single numerical value for single-band images, and a tuple for\n", " | multi-band images. In addition to this, RGB and RGBA tuples are\n", " | accepted for P images.\n", " | \n", " | Note that this method is relatively slow. For more extensive changes,\n", " | use :py:meth:`~PIL.Image.Image.paste` or the :py:mod:`~PIL.ImageDraw`\n", " | module instead.\n", " | \n", " | See:\n", " | \n", " | * :py:meth:`~PIL.Image.Image.paste`\n", " | * :py:meth:`~PIL.Image.Image.putdata`\n", " | * :py:mod:`~PIL.ImageDraw`\n", " | \n", " | :param xy: The pixel coordinate, given as (x, y). See\n", " | :ref:`coordinate-system`.\n", " | :param value: The pixel value.\n", " | \n", " | quantize(self, colors=256, method=None, kmeans=0, palette=None)\n", " | Convert the image to 'P' mode with the specified number\n", " | of colors.\n", " | \n", " | :param colors: The desired number of colors, <= 256\n", " | :param method: 0 = median cut\n", " | 1 = maximum coverage\n", " | 2 = fast octree\n", " | 3 = libimagequant\n", " | :param kmeans: Integer\n", " | :param palette: Quantize to the palette of given\n", " | :py:class:`PIL.Image.Image`.\n", " | :returns: A new image\n", " | \n", " | remap_palette(self, dest_map, source_palette=None)\n", " | Rewrites the image to reorder the palette.\n", " | \n", " | :param dest_map: A list of indexes into the original palette.\n", " | e.g. [1,0] would swap a two item palette, and list(range(255))\n", " | is the identity transform.\n", " | :param source_palette: Bytes or None.\n", " | :returns: An :py:class:`~PIL.Image.Image` object.\n", " | \n", " | resize(self, size, resample=0, box=None)\n", " | Returns a resized copy of this image.\n", " | \n", " | :param size: The requested size in pixels, as a 2-tuple:\n", " | (width, height).\n", " | :param resample: An optional resampling filter. This can be\n", " | one of :py:attr:`PIL.Image.NEAREST`, :py:attr:`PIL.Image.BOX`,\n", " | :py:attr:`PIL.Image.BILINEAR`, :py:attr:`PIL.Image.HAMMING`,\n", " | :py:attr:`PIL.Image.BICUBIC` or :py:attr:`PIL.Image.LANCZOS`.\n", " | If omitted, or if the image has mode \"1\" or \"P\", it is\n", " | set :py:attr:`PIL.Image.NEAREST`.\n", " | See: :ref:`concept-filters`.\n", " | :param box: An optional 4-tuple of floats giving the region\n", " | of the source image which should be scaled.\n", " | The values should be within (0, 0, width, height) rectangle.\n", " | If omitted or None, the entire source is used.\n", " | :returns: An :py:class:`~PIL.Image.Image` object.\n", " | \n", " | rotate(self, angle, resample=0, expand=0, center=None, translate=None, fillcolor=None)\n", " | Returns a rotated copy of this image. This method returns a\n", " | copy of this image, rotated the given number of degrees counter\n", " | clockwise around its centre.\n", " | \n", " | :param angle: In degrees counter clockwise.\n", " | :param resample: An optional resampling filter. This can be\n", " | one of :py:attr:`PIL.Image.NEAREST` (use nearest neighbour),\n", " | :py:attr:`PIL.Image.BILINEAR` (linear interpolation in a 2x2\n", " | environment), or :py:attr:`PIL.Image.BICUBIC`\n", " | (cubic spline interpolation in a 4x4 environment).\n", " | If omitted, or if the image has mode \"1\" or \"P\", it is\n", " | set :py:attr:`PIL.Image.NEAREST`. See :ref:`concept-filters`.\n", " | :param expand: Optional expansion flag. If true, expands the output\n", " | image to make it large enough to hold the entire rotated image.\n", " | If false or omitted, make the output image the same size as the\n", " | input image. Note that the expand flag assumes rotation around\n", " | the center and no translation.\n", " | :param center: Optional center of rotation (a 2-tuple). Origin is\n", " | the upper left corner. Default is the center of the image.\n", " | :param translate: An optional post-rotate translation (a 2-tuple).\n", " | :param fillcolor: An optional color for area outside the rotated image.\n", " | :returns: An :py:class:`~PIL.Image.Image` object.\n", " | \n", " | save(self, fp, format=None, **params)\n", " | Saves this image under the given filename. If no format is\n", " | specified, the format to use is determined from the filename\n", " | extension, if possible.\n", " | \n", " | Keyword options can be used to provide additional instructions\n", " | to the writer. If a writer doesn't recognise an option, it is\n", " | silently ignored. The available options are described in the\n", " | :doc:`image format documentation\n", " | <../handbook/image-file-formats>` for each writer.\n", " | \n", " | You can use a file object instead of a filename. In this case,\n", " | you must always specify the format. The file object must\n", " | implement the ``seek``, ``tell``, and ``write``\n", " | methods, and be opened in binary mode.\n", " | \n", " | :param fp: A filename (string), pathlib.Path object or file object.\n", " | :param format: Optional format override. If omitted, the\n", " | format to use is determined from the filename extension.\n", " | If a file object was used instead of a filename, this\n", " | parameter should always be used.\n", " | :param params: Extra parameters to the image writer.\n", " | :returns: None\n", " | :exception ValueError: If the output format could not be determined\n", " | from the file name. Use the format option to solve this.\n", " | :exception IOError: If the file could not be written. The file\n", " | may have been created, and may contain partial data.\n", " | \n", " | seek(self, frame)\n", " | Seeks to the given frame in this sequence file. If you seek\n", " | beyond the end of the sequence, the method raises an\n", " | **EOFError** exception. When a sequence file is opened, the\n", " | library automatically seeks to frame 0.\n", " | \n", " | Note that in the current version of the library, most sequence\n", " | formats only allows you to seek to the next frame.\n", " | \n", " | See :py:meth:`~PIL.Image.Image.tell`.\n", " | \n", " | :param frame: Frame number, starting at 0.\n", " | :exception EOFError: If the call attempts to seek beyond the end\n", " | of the sequence.\n", " | \n", " | show(self, title=None, command=None)\n", " | Displays this image. This method is mainly intended for\n", " | debugging purposes.\n", " | \n", " | On Unix platforms, this method saves the image to a temporary\n", " | PPM file, and calls either the **xv** utility or the **display**\n", " | utility, depending on which one can be found.\n", " | \n", " | On macOS, this method saves the image to a temporary BMP file, and\n", " | opens it with the native Preview application.\n", " | \n", " | On Windows, it saves the image to a temporary BMP file, and uses\n", " | the standard BMP display utility to show it (usually Paint).\n", " | \n", " | :param title: Optional title to use for the image window,\n", " | where possible.\n", " | :param command: command used to show the image\n", " | \n", " | split(self)\n", " | Split this image into individual bands. This method returns a\n", " | tuple of individual image bands from an image. For example,\n", " | splitting an \"RGB\" image creates three new images each\n", " | containing a copy of one of the original bands (red, green,\n", " | blue).\n", " | \n", " | If you need only one band, :py:meth:`~PIL.Image.Image.getchannel`\n", " | method can be more convenient and faster.\n", " | \n", " | :returns: A tuple containing bands.\n", " | \n", " | tell(self)\n", " | Returns the current frame number. See :py:meth:`~PIL.Image.Image.seek`.\n", " | \n", " | :returns: Frame number, starting with 0.\n", " | \n", " | thumbnail(self, size, resample=3)\n", " | Make this image into a thumbnail. This method modifies the\n", " | image to contain a thumbnail version of itself, no larger than\n", " | the given size. This method calculates an appropriate thumbnail\n", " | size to preserve the aspect of the image, calls the\n", " | :py:meth:`~PIL.Image.Image.draft` method to configure the file reader\n", " | (where applicable), and finally resizes the image.\n", " | \n", " | Note that this function modifies the :py:class:`~PIL.Image.Image`\n", " | object in place. If you need to use the full resolution image as well,\n", " | apply this method to a :py:meth:`~PIL.Image.Image.copy` of the original\n", " | image.\n", " | \n", " | :param size: Requested size.\n", " | :param resample: Optional resampling filter. This can be one\n", " | of :py:attr:`PIL.Image.NEAREST`, :py:attr:`PIL.Image.BILINEAR`,\n", " | :py:attr:`PIL.Image.BICUBIC`, or :py:attr:`PIL.Image.LANCZOS`.\n", " | If omitted, it defaults to :py:attr:`PIL.Image.BICUBIC`.\n", " | (was :py:attr:`PIL.Image.NEAREST` prior to version 2.5.0)\n", " | :returns: None\n", " | \n", " | tobitmap(self, name='image')\n", " | Returns the image converted to an X11 bitmap.\n", " | \n", " | .. note:: This method only works for mode \"1\" images.\n", " | \n", " | :param name: The name prefix to use for the bitmap variables.\n", " | :returns: A string containing an X11 bitmap.\n", " | :raises ValueError: If the mode is not \"1\"\n", " | \n", " | tobytes(self, encoder_name='raw', *args)\n", " | Return image as a bytes object.\n", " | \n", " | .. warning::\n", " | \n", " | This method returns the raw image data from the internal\n", " | storage. For compressed image data (e.g. PNG, JPEG) use\n", " | :meth:`~.save`, with a BytesIO parameter for in-memory\n", " | data.\n", " | \n", " | :param encoder_name: What encoder to use. The default is to\n", " | use the standard \"raw\" encoder.\n", " | :param args: Extra arguments to the encoder.\n", " | :rtype: A bytes object.\n", " | \n", " | toqimage(self)\n", " | Returns a QImage copy of this image\n", " | \n", " | toqpixmap(self)\n", " | Returns a QPixmap copy of this image\n", " | \n", " | tostring(self, *args, **kw)\n", " | \n", " | transform(self, size, method, data=None, resample=0, fill=1, fillcolor=None)\n", " | Transforms this image. This method creates a new image with the\n", " | given size, and the same mode as the original, and copies data\n", " | to the new image using the given transform.\n", " | \n", " | :param size: The output size.\n", " | :param method: The transformation method. This is one of\n", " | :py:attr:`PIL.Image.EXTENT` (cut out a rectangular subregion),\n", " | :py:attr:`PIL.Image.AFFINE` (affine transform),\n", " | :py:attr:`PIL.Image.PERSPECTIVE` (perspective transform),\n", " | :py:attr:`PIL.Image.QUAD` (map a quadrilateral to a rectangle), or\n", " | :py:attr:`PIL.Image.MESH` (map a number of source quadrilaterals\n", " | in one operation).\n", " | \n", " | It may also be an :py:class:`~PIL.Image.ImageTransformHandler`\n", " | object::\n", " | class Example(Image.ImageTransformHandler):\n", " | def transform(size, method, data, resample, fill=1):\n", " | # Return result\n", " | \n", " | It may also be an object with a :py:meth:`~method.getdata` method\n", " | that returns a tuple supplying new **method** and **data** values::\n", " | class Example(object):\n", " | def getdata(self):\n", " | method = Image.EXTENT\n", " | data = (0, 0, 100, 100)\n", " | return method, data\n", " | :param data: Extra data to the transformation method.\n", " | :param resample: Optional resampling filter. It can be one of\n", " | :py:attr:`PIL.Image.NEAREST` (use nearest neighbour),\n", " | :py:attr:`PIL.Image.BILINEAR` (linear interpolation in a 2x2\n", " | environment), or :py:attr:`PIL.Image.BICUBIC` (cubic spline\n", " | interpolation in a 4x4 environment). If omitted, or if the image\n", " | has mode \"1\" or \"P\", it is set to :py:attr:`PIL.Image.NEAREST`.\n", " | :param fill: If **method** is an\n", " | :py:class:`~PIL.Image.ImageTransformHandler` object, this is one of\n", " | the arguments passed to it. Otherwise, it is unused.\n", " | :param fillcolor: Optional fill color for the area outside the\n", " | transform in the output image.\n", " | :returns: An :py:class:`~PIL.Image.Image` object.\n", " | \n", " | transpose(self, method)\n", " | Transpose image (flip or rotate in 90 degree steps)\n", " | \n", " | :param method: One of :py:attr:`PIL.Image.FLIP_LEFT_RIGHT`,\n", " | :py:attr:`PIL.Image.FLIP_TOP_BOTTOM`, :py:attr:`PIL.Image.ROTATE_90`,\n", " | :py:attr:`PIL.Image.ROTATE_180`, :py:attr:`PIL.Image.ROTATE_270`,\n", " | :py:attr:`PIL.Image.TRANSPOSE` or :py:attr:`PIL.Image.TRANSVERSE`.\n", " | :returns: Returns a flipped or rotated copy of this image.\n", " | \n", " | verify(self)\n", " | Verifies the contents of a file. For data read from a file, this\n", " | method attempts to determine if the file is broken, without\n", " | actually decoding the image data. If this method finds any\n", " | problems, it raises suitable exceptions. If you need to load\n", " | the image after using this method, you must reopen the image\n", " | file.\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data descriptors defined here:\n", " | \n", " | __array_interface__\n", " | \n", " | __dict__\n", " | dictionary for instance variables (if defined)\n", " | \n", " | __weakref__\n", " | list of weak references to the object (if defined)\n", " | \n", " | height\n", " | \n", " | size\n", " | \n", " | width\n", " | \n", " | ----------------------------------------------------------------------\n", " | Data and other attributes defined here:\n", " | \n", " | __hash__ = None\n", " | \n", " | format = None\n", " | \n", " | format_description = None\n", " \n", " class ImagePointHandler(builtins.object)\n", " | Data descriptors defined here:\n", " | \n", " | __dict__\n", " | dictionary for instance variables (if defined)\n", " | \n", " | __weakref__\n", " | list of weak references to the object (if defined)\n", " \n", " class ImageTransformHandler(builtins.object)\n", " | Data descriptors defined here:\n", " | \n", " | __dict__\n", " | dictionary for instance variables (if defined)\n", " | \n", " | __weakref__\n", " | list of weak references to the object (if defined)\n", "\n", "FUNCTIONS\n", " alpha_composite(im1, im2)\n", " Alpha composite im2 over im1.\n", " \n", " :param im1: The first image. Must have mode RGBA.\n", " :param im2: The second image. Must have mode RGBA, and the same size as\n", " the first image.\n", " :returns: An :py:class:`~PIL.Image.Image` object.\n", " \n", " blend(im1, im2, alpha)\n", " Creates a new image by interpolating between two input images, using\n", " a constant alpha.::\n", " \n", " out = image1 * (1.0 - alpha) + image2 * alpha\n", " \n", " :param im1: The first image.\n", " :param im2: The second image. Must have the same mode and size as\n", " the first image.\n", " :param alpha: The interpolation alpha factor. If alpha is 0.0, a\n", " copy of the first image is returned. If alpha is 1.0, a copy of\n", " the second image is returned. There are no restrictions on the\n", " alpha value. If necessary, the result is clipped to fit into\n", " the allowed output range.\n", " :returns: An :py:class:`~PIL.Image.Image` object.\n", " \n", " coerce_e(value)\n", " \n", " composite(image1, image2, mask)\n", " Create composite image by blending images using a transparency mask.\n", " \n", " :param image1: The first image.\n", " :param image2: The second image. Must have the same mode and\n", " size as the first image.\n", " :param mask: A mask image. This image can have mode\n", " \"1\", \"L\", or \"RGBA\", and must have the same size as the\n", " other two images.\n", " \n", " effect_mandelbrot(size, extent, quality)\n", " Generate a Mandelbrot set covering the given extent.\n", " \n", " :param size: The requested size in pixels, as a 2-tuple:\n", " (width, height).\n", " :param extent: The extent to cover, as a 4-tuple:\n", " (x0, y0, x1, y2).\n", " :param quality: Quality.\n", " \n", " effect_noise(size, sigma)\n", " Generate Gaussian noise centered around 128.\n", " \n", " :param size: The requested size in pixels, as a 2-tuple:\n", " (width, height).\n", " :param sigma: Standard deviation of noise.\n", " \n", " eval(image, *args)\n", " Applies the function (which should take one argument) to each pixel\n", " in the given image. If the image has more than one band, the same\n", " function is applied to each band. Note that the function is\n", " evaluated once for each possible pixel value, so you cannot use\n", " random components or other generators.\n", " \n", " :param image: The input image.\n", " :param function: A function object, taking one integer argument.\n", " :returns: An :py:class:`~PIL.Image.Image` object.\n", " \n", " fromarray(obj, mode=None)\n", " Creates an image memory from an object exporting the array interface\n", " (using the buffer protocol).\n", " \n", " If **obj** is not contiguous, then the tobytes method is called\n", " and :py:func:`~PIL.Image.frombuffer` is used.\n", " \n", " If you have an image in NumPy::\n", " \n", " from PIL import Image\n", " import numpy as np\n", " im = Image.open('hopper.jpg')\n", " a = np.asarray(im)\n", " \n", " Then this can be used to convert it to a Pillow image::\n", " \n", " im = Image.fromarray(a)\n", " \n", " :param obj: Object with array interface\n", " :param mode: Mode to use (will be determined from type if None)\n", " See: :ref:`concept-modes`.\n", " :returns: An image object.\n", " \n", " .. versionadded:: 1.1.6\n", " \n", " frombuffer(mode, size, data, decoder_name='raw', *args)\n", " Creates an image memory referencing pixel data in a byte buffer.\n", " \n", " This function is similar to :py:func:`~PIL.Image.frombytes`, but uses data\n", " in the byte buffer, where possible. This means that changes to the\n", " original buffer object are reflected in this image). Not all modes can\n", " share memory; supported modes include \"L\", \"RGBX\", \"RGBA\", and \"CMYK\".\n", " \n", " Note that this function decodes pixel data only, not entire images.\n", " If you have an entire image file in a string, wrap it in a\n", " **BytesIO** object, and use :py:func:`~PIL.Image.open` to load it.\n", " \n", " In the current version, the default parameters used for the \"raw\" decoder\n", " differs from that used for :py:func:`~PIL.Image.frombytes`. This is a\n", " bug, and will probably be fixed in a future release. The current release\n", " issues a warning if you do this; to disable the warning, you should provide\n", " the full set of parameters. See below for details.\n", " \n", " :param mode: The image mode. See: :ref:`concept-modes`.\n", " :param size: The image size.\n", " :param data: A bytes or other buffer object containing raw\n", " data for the given mode.\n", " :param decoder_name: What decoder to use.\n", " :param args: Additional parameters for the given decoder. For the\n", " default encoder (\"raw\"), it's recommended that you provide the\n", " full set of parameters::\n", " \n", " frombuffer(mode, size, data, \"raw\", mode, 0, 1)\n", " \n", " :returns: An :py:class:`~PIL.Image.Image` object.\n", " \n", " .. versionadded:: 1.1.4\n", " \n", " frombytes(mode, size, data, decoder_name='raw', *args)\n", " Creates a copy of an image memory from pixel data in a buffer.\n", " \n", " In its simplest form, this function takes three arguments\n", " (mode, size, and unpacked pixel data).\n", " \n", " You can also use any pixel decoder supported by PIL. For more\n", " information on available decoders, see the section\n", " :ref:`Writing Your Own File Decoder `.\n", " \n", " Note that this function decodes pixel data only, not entire images.\n", " If you have an entire image in a string, wrap it in a\n", " :py:class:`~io.BytesIO` object, and use :py:func:`~PIL.Image.open` to load\n", " it.\n", " \n", " :param mode: The image mode. See: :ref:`concept-modes`.\n", " :param size: The image size.\n", " :param data: A byte buffer containing raw data for the given mode.\n", " :param decoder_name: What decoder to use.\n", " :param args: Additional parameters for the given decoder.\n", " :returns: An :py:class:`~PIL.Image.Image` object.\n", " \n", " fromqimage(im)\n", " Creates an image instance from a QImage image\n", " \n", " fromqpixmap(im)\n", " Creates an image instance from a QPixmap image\n", " \n", " fromstring(*args, **kw)\n", " \n", " getmodebandnames(mode)\n", " Gets a list of individual band names. Given a mode, this function returns\n", " a tuple containing the names of individual bands (use\n", " :py:method:`~PIL.Image.getmodetype` to get the mode used to store each\n", " individual band.\n", " \n", " :param mode: Input mode.\n", " :returns: A tuple containing band names. The length of the tuple\n", " gives the number of bands in an image of the given mode.\n", " :exception KeyError: If the input mode was not a standard mode.\n", " \n", " getmodebands(mode)\n", " Gets the number of individual bands for this mode.\n", " \n", " :param mode: Input mode.\n", " :returns: The number of bands in this mode.\n", " :exception KeyError: If the input mode was not a standard mode.\n", " \n", " getmodebase(mode)\n", " Gets the \"base\" mode for given mode. This function returns \"L\" for\n", " images that contain grayscale data, and \"RGB\" for images that\n", " contain color data.\n", " \n", " :param mode: Input mode.\n", " :returns: \"L\" or \"RGB\".\n", " :exception KeyError: If the input mode was not a standard mode.\n", " \n", " getmodetype(mode)\n", " Gets the storage type mode. Given a mode, this function returns a\n", " single-layer mode suitable for storing individual bands.\n", " \n", " :param mode: Input mode.\n", " :returns: \"L\", \"I\", or \"F\".\n", " :exception KeyError: If the input mode was not a standard mode.\n", " \n", " init()\n", " Explicitly initializes the Python Imaging Library. This function\n", " loads all available file format drivers.\n", " \n", " isImageType(t)\n", " Checks if an object is an image object.\n", " \n", " .. warning::\n", " \n", " This function is for internal use only.\n", " \n", " :param t: object to check if it's an image\n", " :returns: True if the object is an image\n", " \n", " linear_gradient(mode)\n", " Generate 256x256 linear gradient from black to white, top to bottom.\n", " \n", " :param mode: Input mode.\n", " \n", " merge(mode, bands)\n", " Merge a set of single band images into a new multiband image.\n", " \n", " :param mode: The mode to use for the output image. See:\n", " :ref:`concept-modes`.\n", " :param bands: A sequence containing one single-band image for\n", " each band in the output image. All bands must have the\n", " same size.\n", " :returns: An :py:class:`~PIL.Image.Image` object.\n", " \n", " new(mode, size, color=0)\n", " Creates a new image with the given mode and size.\n", " \n", " :param mode: The mode to use for the new image. See:\n", " :ref:`concept-modes`.\n", " :param size: A 2-tuple, containing (width, height) in pixels.\n", " :param color: What color to use for the image. Default is black.\n", " If given, this should be a single integer or floating point value\n", " for single-band modes, and a tuple for multi-band modes (one value\n", " per band). When creating RGB images, you can also use color\n", " strings as supported by the ImageColor module. If the color is\n", " None, the image is not initialised.\n", " :returns: An :py:class:`~PIL.Image.Image` object.\n", " \n", " open(fp, mode='r')\n", " Opens and identifies the given image file.\n", " \n", " This is a lazy operation; this function identifies the file, but\n", " the file remains open and the actual image data is not read from\n", " the file until you try to process the data (or call the\n", " :py:meth:`~PIL.Image.Image.load` method). See\n", " :py:func:`~PIL.Image.new`. See :ref:`file-handling`.\n", " \n", " :param fp: A filename (string), pathlib.Path object or a file object.\n", " The file object must implement :py:meth:`~file.read`,\n", " :py:meth:`~file.seek`, and :py:meth:`~file.tell` methods,\n", " and be opened in binary mode.\n", " :param mode: The mode. If given, this argument must be \"r\".\n", " :returns: An :py:class:`~PIL.Image.Image` object.\n", " :exception IOError: If the file cannot be found, or the image cannot be\n", " opened and identified.\n", " \n", " preinit()\n", " Explicitly load standard file format drivers.\n", " \n", " radial_gradient(mode)\n", " Generate 256x256 radial gradient from black to white, centre to edge.\n", " \n", " :param mode: Input mode.\n", " \n", " register_decoder(name, decoder)\n", " Registers an image decoder. This function should not be\n", " used in application code.\n", " \n", " :param name: The name of the decoder\n", " :param decoder: A callable(mode, args) that returns an\n", " ImageFile.PyDecoder object\n", " \n", " .. versionadded:: 4.1.0\n", " \n", " register_encoder(name, encoder)\n", " Registers an image encoder. This function should not be\n", " used in application code.\n", " \n", " :param name: The name of the encoder\n", " :param encoder: A callable(mode, args) that returns an\n", " ImageFile.PyEncoder object\n", " \n", " .. versionadded:: 4.1.0\n", " \n", " register_extension(id, extension)\n", " Registers an image extension. This function should not be\n", " used in application code.\n", " \n", " :param id: An image format identifier.\n", " :param extension: An extension used for this format.\n", " \n", " register_extensions(id, extensions)\n", " Registers image extensions. This function should not be\n", " used in application code.\n", " \n", " :param id: An image format identifier.\n", " :param extensions: A list of extensions used for this format.\n", " \n", " register_mime(id, mimetype)\n", " Registers an image MIME type. This function should not be used\n", " in application code.\n", " \n", " :param id: An image format identifier.\n", " :param mimetype: The image MIME type for this format.\n", " \n", " register_open(id, factory, accept=None)\n", " Register an image file plugin. This function should not be used\n", " in application code.\n", " \n", " :param id: An image format identifier.\n", " :param factory: An image file factory method.\n", " :param accept: An optional function that can be used to quickly\n", " reject images having another format.\n", " \n", " register_save(id, driver)\n", " Registers an image save function. This function should not be\n", " used in application code.\n", " \n", " :param id: An image format identifier.\n", " :param driver: A function to save images in this format.\n", " \n", " register_save_all(id, driver)\n", " Registers an image function to save all the frames\n", " of a multiframe format. This function should not be\n", " used in application code.\n", " \n", " :param id: An image format identifier.\n", " :param driver: A function to save images in this format.\n", " \n", " registered_extensions()\n", " Returns a dictionary containing all file extensions belonging\n", " to registered plugins\n", "\n", "DATA\n", " ADAPTIVE = 1\n", " AFFINE = 0\n", " ANTIALIAS = 1\n", " BICUBIC = 3\n", " BILINEAR = 2\n", " BOX = 4\n", " CONTAINER = 2\n", " CUBIC = 3\n", " DECODERS = {}\n", " DEFAULT_STRATEGY = 0\n", " ENCODERS = {}\n", " EXTENSION = {}\n", " EXTENT = 1\n", " FASTOCTREE = 2\n", " FILTERED = 1\n", " FIXED = 4\n", " FLIP_LEFT_RIGHT = 0\n", " FLIP_TOP_BOTTOM = 1\n", " FLOYDSTEINBERG = 3\n", " HAMMING = 5\n", " HAS_PATHLIB = True\n", " HUFFMAN_ONLY = 2\n", " ID = []\n", " LANCZOS = 1\n", " LIBIMAGEQUANT = 3\n", " LINEAR = 2\n", " MAXCOVERAGE = 1\n", " MAX_IMAGE_PIXELS = 89478485\n", " MEDIANCUT = 0\n", " MESH = 4\n", " MIME = {}\n", " MODES = ['1', 'CMYK', 'F', 'HSV', 'I', 'L', 'LAB', 'P', 'RGB', 'RGBA',...\n", " NEAREST = 0\n", " NONE = 0\n", " NORMAL = 0\n", " OPEN = {}\n", " ORDERED = 1\n", " PERSPECTIVE = 2\n", " PILLOW_VERSION = '5.4.1'\n", " QUAD = 3\n", " RASTERIZE = 2\n", " RLE = 3\n", " ROTATE_180 = 3\n", " ROTATE_270 = 4\n", " ROTATE_90 = 2\n", " SAVE = {}\n", " SAVE_ALL = {}\n", " SEQUENCE = 1\n", " TRANSPOSE = 5\n", " TRANSVERSE = 6\n", " USE_CFFI_ACCESS = False\n", " VERSION = '1.1.7'\n", " WEB = 0\n", " cffi = None\n", " logger = \n", " py3 = True\n", "\n", "VERSION\n", " 5.4.1\n", "\n", "FILE\n", " /home/python/anaconda3/envs/dl_nlp/lib/python3.5/site-packages/PIL/Image.py\n", "\n", "\n" ] } ], "source": [ "help(Image)" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [], "source": [ "# 定义数据生成器\n", "from tensorflow.keras.utils import Sequence\n", "\n", "class CaptchaSequence(Sequence):\n", " '''\n", " 继承Sequence的数据生成类,方便调用多CPU,加快生成训练及测试数据\n", " 参数:self.characters:验证码字符集合,self.batch_size:每批次样本数,self.steps:生成多少批数据,self.n_len:验证码长度,\n", " self.width:图片宽度,self.height:图片高度,self.input_length:lstm time step长度,self.label_length:标签长度\n", " 返回:array类型训练或测试数据 \n", " \n", " '''\n", " def __init__(self, characters, batch_size, steps, n_len=6, width=100, height=50, \n", " input_length=12, label_length=6, chars_len=(4, 4)): # width=128, height=64, input_length=16, label_length=4\n", " self.characters = characters\n", " self.batch_size = batch_size\n", " self.steps = steps\n", " self.n_len = n_len\n", " self.width = width\n", " self.height = height\n", " self.input_length = input_length\n", " self.label_length = label_length\n", " self.chars_len = chars_len\n", "# self.label_length = self.n_len\n", " self.n_class = len(characters)\n", " self.generator = ImageCaptcha(width=width, height=height, font_sizes=(12,20,18,25))\n", " \n", " def __len__(self):\n", " return self.steps\n", "\n", " def __getitem__(self, idx):\n", " X = np.zeros((self.batch_size, self.height, self.width, 3), dtype=np.float32)\n", " y = np.zeros((self.batch_size, self.n_len), dtype=np.uint8)\n", " input_length = np.ones(self.batch_size)*self.input_length\n", " label_length = np.ones(self.batch_size)*self.label_length \n", " for i in range(self.batch_size): \n", " if i % 2 == 0:\n", " image, random_str = rebuild_img(random.choice(glob.glob('Chinese/*.jpg'))) \n", " if i % 2 == 1: \n", " random_str = ''.join([random.choice(self.characters) for j in range(random.randint(self.chars_len[0],self.chars_len[1]))])\n", " image = generate_image(random_str, 100, 25) \n", "# elif i % 2 == 0:\n", "# random_str = ''.join([random.choice(self.characters) for j in range(random.randint(self.chars_len[0],self.chars_len[1]))])\n", "# image = self.generator.generate_image(random_str) \n", "# elif i % 4 == 3:\n", "# image, random_str = rebuild_img(random.choice(glob.glob('Digit5/*.jpg'))) \n", " X[i] = np.array(image)/255.0\n", " label = [self.characters.find(x) for x in random_str]\n", " if len(random_str) < self.n_len:\n", " label += [self.n_class]*(self.n_len-len(random_str)) \n", " y[i] = label\n", "\n", " return [X, y, input_length, label_length], np.ones(self.batch_size)\n" ] }, { "cell_type": "code", "execution_count": 31, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "生生他乐\n" ] }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "image/png": { "height": 200, "width": 370 }, "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "# 测试生成器\n", "# import matplotlib\n", "# # matplotlib.use('qt4agg')\n", "# #指定默认字体\n", "# matplotlib.rcParams['font.sans-serif'] = ['SimHei']\n", "# matplotlib.rcParams['font.family']='sans-serif'\n", "# #解决负号'-'显示为方块的问题\n", "# matplotlib.rcParams['axes.unicode_minus'] = False\n", "\n", "data = CaptchaSequence(characters, batch_size=10, steps=1)\n", "[X_test, y_test, input_length, label_length], _ = data[0]\n", "idx = 0\n", "plt.imshow(X_test[idx])\n", "#plt.title(''.join([characters[x] for x in y_test[idx] if x < len(characters)]))\n", "print(''.join([characters[x] for x in y_test[idx] if x < len(characters)]))\n", "# print(input_length, label_length)\n", "# print(y_test)\n", "# print(X_test.shape)\n", "# print(n_class)" ] }, { "cell_type": "code", "execution_count": 233, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "(1, 30, 80, 3)\n" ] }, { "data": { "text/plain": [ "" ] }, "execution_count": 233, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "image/png": { "height": 158, "width": 370 }, "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "# 从现有图片生成测试数据\n", "def get_data(img_path):\n", " img = Image.open(img_path)\n", "# img = img.crop((0, height-25, width, height))\n", " w, h = img.size\n", " data = np.zeros((1,h, w, 3))\n", " data[0] = np.array(img)/255.0\n", " return data\n", "img_path = '../FileInfo/ffc510f4-f977-11e9-b970-408d5cd36814_5802.jpg'\n", "\n", "data = get_data(img_path)\n", "print(data.shape)\n", "plt.imshow(data[0])" ] }, { "cell_type": "code", "execution_count": 38, "metadata": {}, "outputs": [], "source": [ "# 准确率回调函数\n", "from tqdm import tqdm\n", "\n", "def evaluate(model, batch_size=128, steps=1):\n", " '''\n", " 准确率验证函数,每批次的验证码长度必须一致\n", " ''' \n", " batch_acc = 0\n", " valid_data = CaptchaSequence(characters, batch_size, steps)\n", " for i in range(len(valid_data)):\n", " [X_test, y_test, _, _], _ = valid_data[i]\n", " y_pred = base_model.predict(X_test)\n", " shape = y_pred.shape\n", " # out = K.get_value(K.ctc_decode(y_pred, input_length=np.ones(shape[0])*shape[1],)[0][0])[:, :4]\n", " out = K.get_value(K.ctc_decode(y_pred, input_length=np.ones(shape[0])*shape[1],)[0][0])[:, :]\n", " # print(y_test)\n", " # print(type(y_test))\n", " # print(y_test[y_test<10, axis=1])\n", " # print(out)\n", " if out.shape[1] >= 4:\n", " batch_acc += (y_test[:,:out.shape[1]] == out).all(axis=1).mean()\n", " return batch_acc / steps" ] }, { "cell_type": "code", "execution_count": 40, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0.27000000000000002" ] }, "execution_count": 40, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# model.load_weights('digit4to6_ctc_best2.h5')\n", "evaluate(base_model,batch_size=1, steps=10)" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [], "source": [ "from tensorflow.keras.callbacks import Callback\n", "\n", "class Evaluate(Callback):\n", " '''\n", " 准确率验证的类,每批次的验证码长度必须一致\n", " ''' \n", " def __init__(self):\n", " self.accs = []\n", " \n", " def on_epoch_end(self, epoch, logs=None):\n", " logs = logs or {}\n", " acc = evaluate(base_model, batch_size=128) # evaluate(base_model)\n", " logs['val_acc'] = acc\n", " self.accs.append(acc)\n", " print('\\nacc%.4f'%acc)\n", "# print(f'\\nacc: {acc*100:.4f}')" ] }, { "cell_type": "code", "execution_count": 123, "metadata": { "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Epoch 1/200\n", "1000/1000 [==============================] - 193s 193ms/step - loss: 0.0189 - val_loss: 0.0093\n", "Epoch 2/200\n", "1000/1000 [==============================] - 180s 180ms/step - loss: 0.0143 - val_loss: 0.0282\n", "Epoch 3/200\n", "1000/1000 [==============================] - 178s 178ms/step - loss: 0.0074 - val_loss: 0.0017\n", "Epoch 4/200\n", "1000/1000 [==============================] - 175s 175ms/step - loss: 0.0068 - val_loss: 0.0075\n", "Epoch 5/200\n", "1000/1000 [==============================] - 179s 179ms/step - loss: 0.0040 - val_loss: 0.0146\n", "Epoch 6/200\n", "1000/1000 [==============================] - 177s 177ms/step - loss: 0.0040 - val_loss: 0.0018\n", "Epoch 7/200\n", "1000/1000 [==============================] - 176s 176ms/step - loss: 0.0051 - val_loss: 0.0052\n", "Epoch 8/200\n", "1000/1000 [==============================] - 178s 178ms/step - loss: 0.0030 - val_loss: 0.0019\n" ] }, { "data": { "text/plain": [ "" ] }, "execution_count": 123, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Evaluate()\n", "# 模型训练\n", "from tensorflow.keras.callbacks import EarlyStopping, CSVLogger, ModelCheckpoint\n", "from tensorflow.keras.optimizers import *\n", "# model.load_weights('digit4to6_ctc_best.h5')\n", "\n", "train_data = CaptchaSequence(characters, batch_size=128, steps=1000) # (characters, batch_size=128, steps=1000)\n", "valid_data = CaptchaSequence(characters, batch_size=128, steps=100) # (characters, batch_size=128, steps=100)\n", "# callbacks = [EarlyStopping(patience=5), Evaluate(), \n", "# CSVLogger('ctc.csv'), ModelCheckpoint('ctc_best.h5', save_best_only=True)]\n", "callbacks = [EarlyStopping(patience=5),ModelCheckpoint('gru_chinese4to6_ctc_best.h5', save_best_only=True)]\n", "model.compile(loss={'ctc': lambda y_true, y_pred: y_pred}, optimizer=Adam(1e-3, amsgrad=True))\n", "# model.fit_generator(train_data, epochs=100, validation_data=valid_data,\n", "# callbacks=callbacks)\n", "model.fit_generator(train_data, epochs=200, validation_data=valid_data, workers=4, use_multiprocessing=True,\n", " callbacks=callbacks)" ] }, { "cell_type": "code", "execution_count": 132, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Epoch 1/200\n", "1000/1000 [==============================] - 148s 148ms/step - loss: 0.0022 - val_loss: 0.0019\n", "Epoch 2/200\n", "1000/1000 [==============================] - 135s 135ms/step - loss: 0.0014 - val_loss: 0.0015\n", "Epoch 3/200\n", "1000/1000 [==============================] - 135s 135ms/step - loss: 0.0019 - val_loss: 0.0013\n", "Epoch 4/200\n", "1000/1000 [==============================] - 147s 147ms/step - loss: 0.0011 - val_loss: 0.0011\n", "Epoch 5/200\n", "1000/1000 [==============================] - 151s 151ms/step - loss: 0.0011 - val_loss: 0.0013\n", "Epoch 6/200\n", "1000/1000 [==============================] - 147s 147ms/step - loss: 0.0017 - val_loss: 0.0017\n", "Epoch 7/200\n", "1000/1000 [==============================] - 147s 147ms/step - loss: 0.0013 - val_loss: 0.0012\n", "Epoch 8/200\n", "1000/1000 [==============================] - 150s 150ms/step - loss: 8.4861e-04 - val_loss: 0.0023\n", "Epoch 9/200\n", "1000/1000 [==============================] - 132s 132ms/step - loss: 0.0013 - val_loss: 4.2027e-04\n", "Epoch 10/200\n", "1000/1000 [==============================] - 144s 144ms/step - loss: 9.6570e-04 - val_loss: 0.0012\n", "Epoch 11/200\n", "1000/1000 [==============================] - 138s 138ms/step - loss: 9.1251e-04 - val_loss: 0.0020\n", "Epoch 12/200\n", "1000/1000 [==============================] - 143s 143ms/step - loss: 9.2198e-04 - val_loss: 0.0012\n", "Epoch 13/200\n", "1000/1000 [==============================] - 130s 130ms/step - loss: 7.1544e-04 - val_loss: 9.0678e-04\n", "Epoch 14/200\n", "1000/1000 [==============================] - 133s 133ms/step - loss: 0.0013 - val_loss: 2.1233e-04\n", "Epoch 15/200\n", "1000/1000 [==============================] - 128s 128ms/step - loss: 6.3636e-04 - val_loss: 4.5492e-04\n", "Epoch 16/200\n", "1000/1000 [==============================] - 138s 138ms/step - loss: 9.3961e-04 - val_loss: 7.2916e-04\n", "Epoch 17/200\n", "1000/1000 [==============================] - 137s 137ms/step - loss: 6.8449e-04 - val_loss: 5.1597e-04\n", "Epoch 18/200\n", "1000/1000 [==============================] - 144s 144ms/step - loss: 0.0011 - val_loss: 0.0016\n", "Epoch 19/200\n", "1000/1000 [==============================] - 144s 144ms/step - loss: 8.3182e-04 - val_loss: 2.4117e-04\n", "Epoch 20/200\n", "1000/1000 [==============================] - 161s 161ms/step - loss: 7.8943e-04 - val_loss: 8.6554e-04\n", "Epoch 21/200\n", "1000/1000 [==============================] - 141s 141ms/step - loss: 7.1800e-04 - val_loss: 0.0011\n", "Epoch 22/200\n", "1000/1000 [==============================] - 179s 179ms/step - loss: 4.6494e-04 - val_loss: 8.2405e-04\n", "Epoch 23/200\n", "1000/1000 [==============================] - 158s 158ms/step - loss: 8.2226e-04 - val_loss: 8.0589e-04\n", "Epoch 24/200\n", "1000/1000 [==============================] - 152s 152ms/step - loss: 9.1601e-04 - val_loss: 5.9193e-04\n", "Epoch 25/200\n", "1000/1000 [==============================] - 142s 142ms/step - loss: 7.9299e-04 - val_loss: 0.0012\n", "Epoch 26/200\n", "1000/1000 [==============================] - 133s 133ms/step - loss: 6.9029e-04 - val_loss: 8.5651e-04\n", "Epoch 27/200\n", "1000/1000 [==============================] - 128s 128ms/step - loss: 6.7174e-04 - val_loss: 4.1511e-04\n", "Epoch 28/200\n", "1000/1000 [==============================] - 136s 136ms/step - loss: 6.0534e-04 - val_loss: 2.6149e-04\n", "Epoch 29/200\n", "1000/1000 [==============================] - 138s 138ms/step - loss: 6.4881e-04 - val_loss: 4.1703e-04\n", "Epoch 30/200\n", "1000/1000 [==============================] - 136s 136ms/step - loss: 9.0451e-04 - val_loss: 6.3594e-04\n", "Epoch 31/200\n", "1000/1000 [==============================] - 128s 128ms/step - loss: 8.0347e-04 - val_loss: 3.9353e-04\n", "Epoch 32/200\n", "1000/1000 [==============================] - 134s 134ms/step - loss: 5.0034e-04 - val_loss: 0.0011\n", "Epoch 33/200\n", "1000/1000 [==============================] - 131s 131ms/step - loss: 6.2562e-04 - val_loss: 8.1447e-05\n", "Epoch 34/200\n", "1000/1000 [==============================] - 134s 134ms/step - loss: 5.4361e-04 - val_loss: 8.6071e-04\n", "Epoch 35/200\n", "1000/1000 [==============================] - 128s 128ms/step - loss: 4.0847e-04 - val_loss: 5.8973e-04\n", "Epoch 36/200\n", "1000/1000 [==============================] - 132s 132ms/step - loss: 7.5903e-04 - val_loss: 0.0010\n", "Epoch 37/200\n", "1000/1000 [==============================] - 131s 131ms/step - loss: 8.0659e-04 - val_loss: 3.7447e-04\n", "Epoch 38/200\n", "1000/1000 [==============================] - 128s 128ms/step - loss: 4.2973e-04 - val_loss: 2.5073e-04\n", "Epoch 39/200\n", "1000/1000 [==============================] - 137s 137ms/step - loss: 7.6056e-04 - val_loss: 0.0017\n", "Epoch 40/200\n", "1000/1000 [==============================] - 137s 137ms/step - loss: 5.7833e-04 - val_loss: 5.6634e-04\n", "Epoch 41/200\n", "1000/1000 [==============================] - 132s 132ms/step - loss: 6.4726e-04 - val_loss: 9.2327e-04\n", "Epoch 42/200\n", "1000/1000 [==============================] - 127s 127ms/step - loss: 8.1730e-04 - val_loss: 0.0011\n", "Epoch 43/200\n", "1000/1000 [==============================] - 133s 133ms/step - loss: 5.6135e-04 - val_loss: 7.5791e-04\n", "Epoch 44/200\n", "1000/1000 [==============================] - 131s 131ms/step - loss: 7.3955e-04 - val_loss: 5.0566e-04\n", "Epoch 45/200\n", "1000/1000 [==============================] - 131s 131ms/step - loss: 5.7832e-04 - val_loss: 8.8573e-04\n", "Epoch 46/200\n", "1000/1000 [==============================] - 127s 127ms/step - loss: 3.3648e-04 - val_loss: 8.1765e-04\n", "Epoch 47/200\n", "1000/1000 [==============================] - 138s 138ms/step - loss: 6.7850e-04 - val_loss: 4.2928e-04\n", "Epoch 48/200\n", "1000/1000 [==============================] - 135s 135ms/step - loss: 6.3248e-04 - val_loss: 9.6712e-04\n", "Epoch 49/200\n", "1000/1000 [==============================] - 132s 132ms/step - loss: 5.1584e-04 - val_loss: 1.8368e-04\n", "Epoch 50/200\n", "1000/1000 [==============================] - 128s 128ms/step - loss: 3.3176e-04 - val_loss: 3.2549e-04\n", "Epoch 51/200\n", "1000/1000 [==============================] - 141s 141ms/step - loss: 6.8528e-04 - val_loss: 3.5227e-04\n", "Epoch 52/200\n", "1000/1000 [==============================] - 132s 132ms/step - loss: 6.9828e-04 - val_loss: 0.0015\n", "Epoch 53/200\n", "1000/1000 [==============================] - 128s 128ms/step - loss: 3.0474e-04 - val_loss: 5.6425e-04\n", "Epoch 54/200\n", "1000/1000 [==============================] - 134s 134ms/step - loss: 2.8557e-04 - val_loss: 0.0013\n", "Epoch 55/200\n", "1000/1000 [==============================] - 132s 132ms/step - loss: 3.4458e-04 - val_loss: 5.5906e-05\n", "Epoch 56/200\n", "1000/1000 [==============================] - 142s 142ms/step - loss: 3.4835e-04 - val_loss: 6.1277e-04\n", "Epoch 57/200\n", "1000/1000 [==============================] - 135s 135ms/step - loss: 5.0905e-04 - val_loss: 4.8956e-04\n", "Epoch 58/200\n", "1000/1000 [==============================] - 127s 127ms/step - loss: 5.6468e-04 - val_loss: 5.7344e-04\n", "Epoch 59/200\n", "1000/1000 [==============================] - 133s 133ms/step - loss: 4.4183e-04 - val_loss: 1.7794e-04\n", "Epoch 60/200\n", "1000/1000 [==============================] - 129s 129ms/step - loss: 4.5412e-04 - val_loss: 1.6041e-04\n", "Epoch 61/200\n", "1000/1000 [==============================] - 128s 128ms/step - loss: 4.9852e-04 - val_loss: 4.3840e-04\n", "Epoch 62/200\n", "1000/1000 [==============================] - 134s 134ms/step - loss: 6.7447e-04 - val_loss: 1.6152e-04\n", "Epoch 63/200\n", "1000/1000 [==============================] - 136s 136ms/step - loss: 3.8992e-04 - val_loss: 2.8238e-04\n", "Epoch 64/200\n", "1000/1000 [==============================] - 139s 139ms/step - loss: 4.0332e-04 - val_loss: 3.3738e-04\n", "Epoch 65/200\n", "1000/1000 [==============================] - 137s 137ms/step - loss: 7.9051e-04 - val_loss: 5.3923e-04\n", "Epoch 66/200\n", "1000/1000 [==============================] - 142s 142ms/step - loss: 4.0048e-04 - val_loss: 1.5089e-04\n", "Epoch 67/200\n", "1000/1000 [==============================] - 132s 132ms/step - loss: 5.6574e-04 - val_loss: 0.0016\n", "Epoch 68/200\n", "1000/1000 [==============================] - 133s 133ms/step - loss: 5.4310e-04 - val_loss: 9.8526e-04\n", "Epoch 69/200\n", "1000/1000 [==============================] - 127s 127ms/step - loss: 3.4376e-04 - val_loss: 0.0017\n", "Epoch 70/200\n", "1000/1000 [==============================] - 131s 131ms/step - loss: 4.1208e-04 - val_loss: 5.6815e-04\n", "Epoch 71/200\n", "1000/1000 [==============================] - 132s 132ms/step - loss: 4.5194e-04 - val_loss: 5.6555e-04\n", "Epoch 72/200\n", "1000/1000 [==============================] - 133s 133ms/step - loss: 4.4922e-04 - val_loss: 3.4947e-04\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Epoch 73/200\n", "1000/1000 [==============================] - 141s 141ms/step - loss: 4.7118e-04 - val_loss: 9.7778e-04\n", "Epoch 74/200\n", "1000/1000 [==============================] - 142s 142ms/step - loss: 4.0466e-04 - val_loss: 6.1617e-05\n", "Epoch 75/200\n", "1000/1000 [==============================] - 136s 136ms/step - loss: 3.5813e-04 - val_loss: 5.1262e-05\n", "Epoch 76/200\n", "1000/1000 [==============================] - 137s 137ms/step - loss: 4.7191e-04 - val_loss: 0.0010\n", "Epoch 77/200\n", "1000/1000 [==============================] - 131s 131ms/step - loss: 4.3555e-04 - val_loss: 1.8376e-04\n", "Epoch 78/200\n", "1000/1000 [==============================] - 134s 134ms/step - loss: 4.0705e-04 - val_loss: 6.7844e-04\n", "Epoch 79/200\n", "1000/1000 [==============================] - 137s 137ms/step - loss: 4.9219e-04 - val_loss: 0.0021\n", "Epoch 80/200\n", "1000/1000 [==============================] - 133s 133ms/step - loss: 3.2442e-04 - val_loss: 8.8529e-05\n", "Epoch 81/200\n", "1000/1000 [==============================] - 133s 133ms/step - loss: 3.7665e-04 - val_loss: 3.1958e-04\n", "Epoch 82/200\n", "1000/1000 [==============================] - 127s 127ms/step - loss: 3.3022e-04 - val_loss: 6.1618e-04\n", "Epoch 83/200\n", "1000/1000 [==============================] - 164s 164ms/step - loss: 3.1366e-04 - val_loss: 5.0268e-04\n", "Epoch 84/200\n", "1000/1000 [==============================] - 146s 146ms/step - loss: 2.9759e-04 - val_loss: 5.3258e-04\n", "Epoch 85/200\n", "1000/1000 [==============================] - 136s 136ms/step - loss: 3.0316e-04 - val_loss: 2.0828e-04\n", "Epoch 86/200\n", "1000/1000 [==============================] - 167s 167ms/step - loss: 2.9953e-04 - val_loss: 1.3785e-04\n", "Epoch 87/200\n", "1000/1000 [==============================] - 156s 156ms/step - loss: 5.5878e-04 - val_loss: 9.9202e-04\n", "Epoch 88/200\n", "1000/1000 [==============================] - 167s 167ms/step - loss: 2.5437e-04 - val_loss: 8.7765e-04\n", "Epoch 89/200\n", "1000/1000 [==============================] - 168s 168ms/step - loss: 3.3139e-04 - val_loss: 3.7203e-04\n", "Epoch 90/200\n", "1000/1000 [==============================] - 172s 172ms/step - loss: 2.3046e-04 - val_loss: 1.4707e-04\n", "Epoch 91/200\n", "1000/1000 [==============================] - 185s 185ms/step - loss: 5.2429e-04 - val_loss: 1.4680e-04\n", "Epoch 92/200\n", "1000/1000 [==============================] - 155s 155ms/step - loss: 3.8421e-04 - val_loss: 5.0110e-04\n", "Epoch 93/200\n", "1000/1000 [==============================] - 155s 155ms/step - loss: 3.6926e-04 - val_loss: 6.7226e-05\n", "Epoch 94/200\n", "1000/1000 [==============================] - 153s 153ms/step - loss: 4.3706e-04 - val_loss: 1.6924e-04\n", "Epoch 95/200\n", "1000/1000 [==============================] - 184s 184ms/step - loss: 2.9833e-04 - val_loss: 3.8188e-04\n", "Epoch 96/200\n", "1000/1000 [==============================] - 139s 139ms/step - loss: 4.7341e-04 - val_loss: 1.1833e-04\n", "Epoch 97/200\n", "1000/1000 [==============================] - 160s 160ms/step - loss: 3.6259e-04 - val_loss: 1.6423e-04\n", "Epoch 98/200\n", "1000/1000 [==============================] - 145s 145ms/step - loss: 3.6168e-04 - val_loss: 3.9120e-04\n", "Epoch 99/200\n", "1000/1000 [==============================] - 155s 155ms/step - loss: 6.3326e-04 - val_loss: 2.5644e-04\n", "Epoch 100/200\n", "1000/1000 [==============================] - 152s 152ms/step - loss: 2.1405e-04 - val_loss: 7.8610e-05\n", "Epoch 101/200\n", "1000/1000 [==============================] - 155s 155ms/step - loss: 4.0480e-04 - val_loss: 2.9795e-04\n", "Epoch 102/200\n", "1000/1000 [==============================] - 140s 140ms/step - loss: 1.1597e-04 - val_loss: 7.5157e-04\n", "Epoch 103/200\n", "1000/1000 [==============================] - 152s 152ms/step - loss: 3.3371e-04 - val_loss: 1.8920e-04\n", "Epoch 104/200\n", "1000/1000 [==============================] - 174s 174ms/step - loss: 1.9717e-04 - val_loss: 7.7888e-04\n", "Epoch 105/200\n", "1000/1000 [==============================] - 165s 165ms/step - loss: 2.8389e-04 - val_loss: 6.9948e-04\n", "Epoch 106/200\n", "1000/1000 [==============================] - 159s 159ms/step - loss: 4.8984e-04 - val_loss: 1.1275e-04\n", "Epoch 107/200\n", "1000/1000 [==============================] - 165s 165ms/step - loss: 3.2361e-04 - val_loss: 8.2341e-05\n", "Epoch 108/200\n", "1000/1000 [==============================] - 148s 148ms/step - loss: 2.5608e-04 - val_loss: 9.2121e-05\n", "Epoch 109/200\n", "1000/1000 [==============================] - 152s 152ms/step - loss: 2.4973e-04 - val_loss: 3.6448e-04\n", "Epoch 110/200\n", "1000/1000 [==============================] - 152s 152ms/step - loss: 3.0289e-04 - val_loss: 5.1137e-04\n", "Epoch 111/200\n", "1000/1000 [==============================] - 151s 151ms/step - loss: 2.6364e-04 - val_loss: 3.8012e-04\n", "Epoch 112/200\n", "1000/1000 [==============================] - 152s 152ms/step - loss: 3.1092e-04 - val_loss: 9.0025e-05\n", "Epoch 113/200\n", "1000/1000 [==============================] - 154s 154ms/step - loss: 3.5954e-04 - val_loss: 2.5753e-04\n", "Epoch 114/200\n", "1000/1000 [==============================] - 155s 155ms/step - loss: 2.1781e-04 - val_loss: 5.4620e-04\n", "Epoch 115/200\n", "1000/1000 [==============================] - 158s 158ms/step - loss: 5.4743e-04 - val_loss: 6.3856e-04\n", "Epoch 116/200\n", "1000/1000 [==============================] - 159s 159ms/step - loss: 2.3253e-04 - val_loss: 4.2828e-05\n", "Epoch 117/200\n", "1000/1000 [==============================] - 152s 152ms/step - loss: 2.5912e-04 - val_loss: 4.0321e-04\n", "Epoch 118/200\n", "1000/1000 [==============================] - 151s 151ms/step - loss: 1.9823e-04 - val_loss: 6.6601e-04\n", "Epoch 119/200\n", "1000/1000 [==============================] - 175s 175ms/step - loss: 2.5639e-04 - val_loss: 1.9235e-04\n", "Epoch 120/200\n", "1000/1000 [==============================] - 166s 166ms/step - loss: 3.0179e-04 - val_loss: 3.1955e-04\n", "Epoch 121/200\n", "1000/1000 [==============================] - 145s 145ms/step - loss: 2.7756e-04 - val_loss: 6.0740e-05\n", "Epoch 122/200\n", "1000/1000 [==============================] - 156s 156ms/step - loss: 1.5605e-04 - val_loss: 8.8709e-05\n", "Epoch 123/200\n", "1000/1000 [==============================] - 151s 151ms/step - loss: 1.3895e-04 - val_loss: 3.8306e-04\n", "Epoch 124/200\n", "1000/1000 [==============================] - 140s 140ms/step - loss: 5.0174e-04 - val_loss: 9.4483e-04\n", "Epoch 125/200\n", "1000/1000 [==============================] - 135s 135ms/step - loss: 2.6244e-04 - val_loss: 5.8199e-04\n", "Epoch 126/200\n", "1000/1000 [==============================] - 162s 162ms/step - loss: 2.3098e-04 - val_loss: 7.6534e-04\n", "Epoch 127/200\n", "1000/1000 [==============================] - 160s 160ms/step - loss: 2.2527e-04 - val_loss: 1.2003e-04\n", "Epoch 128/200\n", "1000/1000 [==============================] - 144s 144ms/step - loss: 3.1886e-04 - val_loss: 4.6757e-05\n", "Epoch 129/200\n", "1000/1000 [==============================] - 143s 143ms/step - loss: 1.9210e-04 - val_loss: 1.7622e-04\n", "Epoch 130/200\n", "1000/1000 [==============================] - 131s 131ms/step - loss: 1.6995e-04 - val_loss: 6.0474e-04\n", "Epoch 131/200\n", "1000/1000 [==============================] - 155s 155ms/step - loss: 3.9251e-04 - val_loss: 2.3732e-04\n", "Epoch 132/200\n", "1000/1000 [==============================] - 165s 165ms/step - loss: 3.2859e-04 - val_loss: 8.8457e-04\n", "Epoch 133/200\n", "1000/1000 [==============================] - 179s 179ms/step - loss: 3.2725e-04 - val_loss: 7.6356e-04\n", "Epoch 134/200\n", "1000/1000 [==============================] - 177s 177ms/step - loss: 2.8504e-04 - val_loss: 4.5482e-05\n", "Epoch 135/200\n", "1000/1000 [==============================] - 173s 173ms/step - loss: 3.3432e-04 - val_loss: 5.1810e-05\n", "Epoch 136/200\n", "1000/1000 [==============================] - 181s 181ms/step - loss: 3.7120e-04 - val_loss: 1.6616e-04\n", "Epoch 137/200\n", "1000/1000 [==============================] - 172s 172ms/step - loss: 5.2715e-04 - val_loss: 2.2632e-04\n", "Epoch 138/200\n", "1000/1000 [==============================] - 162s 162ms/step - loss: 3.3806e-04 - val_loss: 3.9023e-04\n", "Epoch 139/200\n", "1000/1000 [==============================] - 149s 149ms/step - loss: 4.5344e-04 - val_loss: 1.0478e-04\n", "Epoch 140/200\n", "1000/1000 [==============================] - 140s 140ms/step - loss: 2.5791e-04 - val_loss: 4.4730e-05\n", "Epoch 141/200\n", "1000/1000 [==============================] - 140s 140ms/step - loss: 2.2369e-04 - val_loss: 4.0237e-05\n", "Epoch 142/200\n", "1000/1000 [==============================] - 160s 160ms/step - loss: 3.1665e-04 - val_loss: 2.8251e-04\n", "Epoch 143/200\n", "1000/1000 [==============================] - 144s 144ms/step - loss: 3.1699e-04 - val_loss: 3.9364e-04\n", "Epoch 144/200\n", "1000/1000 [==============================] - 155s 155ms/step - loss: 2.9475e-04 - val_loss: 5.3194e-04\n", "Epoch 145/200\n", "1000/1000 [==============================] - 168s 168ms/step - loss: 1.8192e-04 - val_loss: 4.2476e-04\n", "Epoch 146/200\n", "1000/1000 [==============================] - 151s 151ms/step - loss: 3.1528e-04 - val_loss: 1.3713e-04\n", "Epoch 147/200\n", "1000/1000 [==============================] - 161s 161ms/step - loss: 2.7575e-04 - val_loss: 1.9793e-04\n", "Epoch 148/200\n", "1000/1000 [==============================] - 131s 131ms/step - loss: 2.6278e-04 - val_loss: 4.9448e-05\n", "Epoch 149/200\n", "1000/1000 [==============================] - 147s 147ms/step - loss: 2.3149e-04 - val_loss: 4.9294e-05\n", "Epoch 150/200\n", "1000/1000 [==============================] - 143s 143ms/step - loss: 2.5669e-04 - val_loss: 2.8017e-04\n", "Epoch 151/200\n", "1000/1000 [==============================] - 147s 147ms/step - loss: 4.3339e-04 - val_loss: 3.7177e-04\n", "Epoch 152/200\n", "1000/1000 [==============================] - 138s 138ms/step - loss: 3.2514e-04 - val_loss: 3.3955e-04\n", "Epoch 153/200\n", "1000/1000 [==============================] - 128s 128ms/step - loss: 2.7291e-04 - val_loss: 1.7034e-04\n", "Epoch 154/200\n", "1000/1000 [==============================] - 134s 134ms/step - loss: 3.0673e-04 - val_loss: 4.8730e-04\n", "Epoch 155/200\n", "1000/1000 [==============================] - 140s 140ms/step - loss: 1.7177e-04 - val_loss: 1.2396e-04\n", "Epoch 156/200\n", "1000/1000 [==============================] - 134s 134ms/step - loss: 3.3942e-04 - val_loss: 5.5243e-04\n", "Epoch 157/200\n", "1000/1000 [==============================] - 134s 134ms/step - loss: 2.7545e-04 - val_loss: 1.0692e-04\n", "Epoch 158/200\n", "1000/1000 [==============================] - 191s 191ms/step - loss: 4.4843e-04 - val_loss: 2.2471e-04\n", "Epoch 159/200\n", "1000/1000 [==============================] - 179s 179ms/step - loss: 2.1976e-04 - val_loss: 5.9007e-04\n", "Epoch 160/200\n", "1000/1000 [==============================] - 179s 179ms/step - loss: 2.1347e-04 - val_loss: 9.3283e-05\n", "Epoch 161/200\n", "1000/1000 [==============================] - 191s 191ms/step - loss: 3.6800e-04 - val_loss: 2.9132e-04\n", "Epoch 162/200\n", "1000/1000 [==============================] - 189s 189ms/step - loss: 2.8488e-04 - val_loss: 5.4163e-05\n", "Epoch 163/200\n", "1000/1000 [==============================] - 207s 207ms/step - loss: 4.0608e-04 - val_loss: 0.0011\n", "Epoch 164/200\n", "1000/1000 [==============================] - 157s 157ms/step - loss: 7.5428e-05 - val_loss: 5.6931e-04\n", "Epoch 165/200\n", "1000/1000 [==============================] - 141s 141ms/step - loss: 3.1403e-04 - val_loss: 9.4617e-04\n", "Epoch 166/200\n", "1000/1000 [==============================] - 141s 141ms/step - loss: 3.1706e-04 - val_loss: 1.2175e-04\n", "Epoch 167/200\n", "1000/1000 [==============================] - 147s 147ms/step - loss: 3.8588e-04 - val_loss: 5.3527e-05\n", "Epoch 168/200\n", "1000/1000 [==============================] - 134s 134ms/step - loss: 4.7640e-04 - val_loss: 2.6696e-04\n", "Epoch 169/200\n", "1000/1000 [==============================] - 128s 128ms/step - loss: 1.5248e-04 - val_loss: 9.3182e-04\n", "Epoch 170/200\n", "1000/1000 [==============================] - 130s 130ms/step - loss: 4.2068e-04 - val_loss: 1.4433e-04\n", "Epoch 171/200\n", "1000/1000 [==============================] - 132s 132ms/step - loss: 3.5989e-04 - val_loss: 2.9496e-04\n", "Epoch 172/200\n", "1000/1000 [==============================] - 129s 129ms/step - loss: 2.0964e-04 - val_loss: 4.2310e-04\n", "Epoch 173/200\n", "1000/1000 [==============================] - 129s 129ms/step - loss: 3.4592e-04 - val_loss: 4.7207e-05\n", "Epoch 174/200\n", "1000/1000 [==============================] - 138s 138ms/step - loss: 2.0662e-04 - val_loss: 6.8104e-05\n", "Epoch 175/200\n", "1000/1000 [==============================] - 135s 135ms/step - loss: 3.4556e-04 - val_loss: 4.1220e-05\n", "Epoch 176/200\n", "1000/1000 [==============================] - 129s 129ms/step - loss: 2.6176e-04 - val_loss: 1.8251e-04\n", "Epoch 177/200\n", "1000/1000 [==============================] - 142s 142ms/step - loss: 1.7802e-04 - val_loss: 3.8866e-05\n", "Epoch 178/200\n", "1000/1000 [==============================] - 132s 132ms/step - loss: 1.4620e-04 - val_loss: 3.1020e-04\n", "Epoch 179/200\n", "1000/1000 [==============================] - 129s 129ms/step - loss: 4.3285e-04 - val_loss: 5.0611e-04\n", "Epoch 180/200\n", "1000/1000 [==============================] - 128s 128ms/step - loss: 1.0268e-04 - val_loss: 3.9714e-05\n", "Epoch 181/200\n", "1000/1000 [==============================] - 129s 129ms/step - loss: 4.2519e-04 - val_loss: 6.2385e-04\n", "Epoch 182/200\n", "1000/1000 [==============================] - 128s 128ms/step - loss: 5.4499e-04 - val_loss: 3.1758e-04\n", "Epoch 183/200\n", "1000/1000 [==============================] - 129s 129ms/step - loss: 2.2264e-04 - val_loss: 4.0469e-05\n", "Epoch 184/200\n", "1000/1000 [==============================] - 128s 128ms/step - loss: 2.3010e-04 - val_loss: 9.7698e-05\n", "Epoch 185/200\n", "1000/1000 [==============================] - 129s 129ms/step - loss: 1.7865e-04 - val_loss: 0.0011\n", "Epoch 186/200\n", "1000/1000 [==============================] - 129s 129ms/step - loss: 1.6911e-04 - val_loss: 4.3421e-04\n", "Epoch 187/200\n", "1000/1000 [==============================] - 128s 128ms/step - loss: 2.0762e-04 - val_loss: 5.3338e-04\n", "Epoch 188/200\n", "1000/1000 [==============================] - 129s 129ms/step - loss: 3.1216e-04 - val_loss: 4.7123e-05\n", "Epoch 189/200\n", "1000/1000 [==============================] - 128s 128ms/step - loss: 3.0157e-04 - val_loss: 2.9809e-04\n", "Epoch 190/200\n", "1000/1000 [==============================] - 128s 128ms/step - loss: 2.0915e-04 - val_loss: 4.9929e-05\n", "Epoch 191/200\n", "1000/1000 [==============================] - 129s 129ms/step - loss: 2.2940e-04 - val_loss: 7.3777e-04\n", "Epoch 192/200\n", "1000/1000 [==============================] - 129s 129ms/step - loss: 2.5145e-04 - val_loss: 5.9462e-04\n", "Epoch 193/200\n", "1000/1000 [==============================] - 129s 129ms/step - loss: 2.0645e-04 - val_loss: 4.9079e-05\n", "Epoch 194/200\n", "1000/1000 [==============================] - 128s 128ms/step - loss: 3.2021e-04 - val_loss: 4.1759e-04\n", "Epoch 195/200\n", "1000/1000 [==============================] - 134s 134ms/step - loss: 2.3751e-04 - val_loss: 6.0537e-05\n", "Epoch 196/200\n", "1000/1000 [==============================] - 128s 128ms/step - loss: 1.8666e-04 - val_loss: 3.6992e-05\n", "Epoch 197/200\n", "1000/1000 [==============================] - 128s 128ms/step - loss: 3.4132e-04 - val_loss: 2.0819e-04\n", "Epoch 198/200\n", "1000/1000 [==============================] - 128s 128ms/step - loss: 1.3914e-04 - val_loss: 5.4176e-04\n", "Epoch 199/200\n", "1000/1000 [==============================] - 130s 130ms/step - loss: 2.5896e-04 - val_loss: 6.1120e-05\n", "Epoch 200/200\n", "1000/1000 [==============================] - 130s 130ms/step - loss: 2.7627e-04 - val_loss: 4.3073e-05\n" ] }, { "data": { "text/plain": [ "" ] }, "execution_count": 132, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# 载入最好的模型继续训练一会\n", "model.load_weights('gru_chinese4to6_ctc_best.h5')\n", "# train_data = CaptchaSequence(characters, batch_size=128, steps=1000) # (characters, batch_size=128, steps=1000)\n", "# valid_data = CaptchaSequence(characters, batch_size=128, steps=100) # (characters, batch_size=128, steps=100)\n", "# callbacks = [EarlyStopping(patience=5),\n", "# CSVLogger('ctc.csv', append=True), ModelCheckpoint('ctc_best.h5', save_best_only=True)]\n", "callbacks = [CSVLogger('ctc.csv', append=True), ModelCheckpoint('gru_chinese4to6_ctc_best.h5', save_best_only=True)]\n", "\n", "model.compile(loss={'ctc': lambda y_true, y_pred: y_pred}, optimizer=Adam(1e-4, amsgrad=True))\n", "model.fit_generator(train_data, epochs=200, validation_data=valid_data, workers=4, use_multiprocessing=True,\n", " callbacks=callbacks)" ] }, { "cell_type": "code", "execution_count": 136, "metadata": {}, "outputs": [], "source": [ "# model.load_weights('ctc_best.h5')\n", "base_model.save('gru_chinese_base_model.h5')" ] }, { "cell_type": "code", "execution_count": 135, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "总耗时: 1.3678092956542969\n", "141 0\n" ] } ], "source": [ "# 测试模型\n", "characters2 = characters + ' '\n", "import time\n", "import re\n", "def get_test_data():\n", " '''\n", " 从本地获取验证码图片并生成测试数据\n", " ''' \n", " X = []\n", " Y = []\n", " for path in glob.glob('Chinese/*.jpg'): # Digit5/*.jpg\n", " random_str = path.split('_')[-1][:-4] \n", " if random_str.isalpha() and len(random_str) ==4:\n", " random_str = random_str.upper()\n", "# print(random_str)\n", "# if random_str.isdigit() and len(random_str) ==4:\n", " img = Image.open(path)\n", " X.append(np.array(img.resize((100,50), Image.BILINEAR))/255.0)\n", " label_idx = [characters.find(x) for x in random_str]\n", " if len(random_str) < n_len:\n", " label_idx += [n_class-1]*(n_len-len(random_str)) \n", " Y.append(label_idx)\n", " return [np.array(X), np.array(Y), np.ones(len(X)), np.ones(len(X))],np.ones(len(X))\n", "\n", "data = [get_test_data()]\n", "\n", "# data = CaptchaSequence(characters, batch_size=128, steps=20, chars_len=(4,4))\n", "\n", "pos = neg = 0\n", "t1 = time.time()\n", "for i in range(len(data)): \n", " flag = False\n", " [X_test, y_test, _, _], _ = data[i]\n", " y_pred = base_model.predict(X_test)\n", "# print(y_pred.shape)\n", " out_pre = K.get_value(K.ctc_decode(y_pred, input_length=np.ones(y_pred.shape[0])*y_pred.shape[1])[0][0])[:, :10]\n", "# print(out_pre.shape)\n", "# print(out)\n", " for j in range(out_pre.shape[0]):\n", " out = ''.join([characters[x] for x in out_pre[j] if x < len(characters)]) \n", " y_true = ''.join([characters[x] for x in y_test[j] if x < len(characters)])\n", "# out = ''.join([characters2[x] for x in out_pre[j] if x < len(characters)]) \n", "# if re.sub(' ','',out) != y_true:\n", " if out != y_true:\n", "# print(' ' in out[-2:])\n", " plt.imshow(X_test[j])\n", " plt.title('pred:' + str(out) + '\\ntrue: ' + str(y_true))\n", " print('pred:' + str(out) + '\\ntrue:' + str(y_true))\n", " neg += 1\n", " flag = True\n", "# break\n", "# time.sleep(1)\n", "# argmax = np.argmax(y_pred, axis=2)[j]\n", "# print(list(zip(argmax, ''.join([characters2[x] for x in argmax]))))\n", " else:\n", "# print('pred:' + str(out) + '\\ntrue: ' + str(y_true))\n", " pos += 1 \n", "\n", "# if flag:\n", "# break\n", "t2 = time.time()\n", "print('总耗时:',t2-t1)\n", "print(pos,neg)\n", "# # plt.imshow(X_test[0])\n", "# # plt.title('pred:' + str(out) + '\\ntrue: ' + str(y_true))\n", "\n", "# argmax = np.argmax(y_pred, axis=2)[0]\n", "# list(zip(argmax, ''.join([characters2[x] for x in argmax])))" ] }, { "cell_type": "code", "execution_count": 199, "metadata": {}, "outputs": [], "source": [ "evaluate(base_model,batch_size=128, steps=10)" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "# 展示损失下降图\n", "import pandas as pd\n", "\n", "df = pd.read_csv('ctc.csv')\n", "df[['loss', 'val_loss']].plot()" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.5.0" } }, "nbformat": 4, "nbformat_minor": 2 }