├── Dataset
├── Clay
├── Water
├── Wheat
├── EuFinal
├── Dalforest
├── Grassland
├── subfebformosat2
└── subfebformosat2.hdr
├── Results
├── Hard_classified.PNG
├── Soft_classification1.PNG
└── Soft_classification2.PNG
├── LICENSE
├── utils.py
├── README.md
└── notebooks
└── Hybrid CNN- RNN Model.ipynb
/Dataset/Clay:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anumitgarg/Hybrid-CNN-RNN-Model-for-Hyperspectral-Satellite-Image-Classification/HEAD/Dataset/Clay
--------------------------------------------------------------------------------
/Dataset/Water:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anumitgarg/Hybrid-CNN-RNN-Model-for-Hyperspectral-Satellite-Image-Classification/HEAD/Dataset/Water
--------------------------------------------------------------------------------
/Dataset/Wheat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anumitgarg/Hybrid-CNN-RNN-Model-for-Hyperspectral-Satellite-Image-Classification/HEAD/Dataset/Wheat
--------------------------------------------------------------------------------
/Dataset/EuFinal:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anumitgarg/Hybrid-CNN-RNN-Model-for-Hyperspectral-Satellite-Image-Classification/HEAD/Dataset/EuFinal
--------------------------------------------------------------------------------
/Dataset/Dalforest:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anumitgarg/Hybrid-CNN-RNN-Model-for-Hyperspectral-Satellite-Image-Classification/HEAD/Dataset/Dalforest
--------------------------------------------------------------------------------
/Dataset/Grassland:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anumitgarg/Hybrid-CNN-RNN-Model-for-Hyperspectral-Satellite-Image-Classification/HEAD/Dataset/Grassland
--------------------------------------------------------------------------------
/Dataset/subfebformosat2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anumitgarg/Hybrid-CNN-RNN-Model-for-Hyperspectral-Satellite-Image-Classification/HEAD/Dataset/subfebformosat2
--------------------------------------------------------------------------------
/Results/Hard_classified.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anumitgarg/Hybrid-CNN-RNN-Model-for-Hyperspectral-Satellite-Image-Classification/HEAD/Results/Hard_classified.PNG
--------------------------------------------------------------------------------
/Results/Soft_classification1.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anumitgarg/Hybrid-CNN-RNN-Model-for-Hyperspectral-Satellite-Image-Classification/HEAD/Results/Soft_classification1.PNG
--------------------------------------------------------------------------------
/Results/Soft_classification2.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anumitgarg/Hybrid-CNN-RNN-Model-for-Hyperspectral-Satellite-Image-Classification/HEAD/Results/Soft_classification2.PNG
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 anumitgarg
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Dataset/subfebformosat2.hdr:
--------------------------------------------------------------------------------
1 | BANDS: 4
2 | ROWS: 436
3 | COLS: 506
4 | INTERLEAVING: BIL
5 | DATATYPE: U8
6 | BYTE_ORDER: NA
7 | UL_X_COORDINATE: 226448.000000
8 | UL_Y_COORDINATE: 3306128.000000
9 | LR_X_COORDINATE: 230488.000000
10 | LR_Y_COORDINATE: 3302648.000000
11 | PIXEL_WIDTH: 8.0000000
12 | PIXEL_HEIGHT: 8.0000000
13 | MAP_UNITS: meters
14 | PROJECTION_NAME: UTM
15 | PROJECTION_ZONE: 44
16 | PROJECTION_PARAMETERS:
17 | 0.000000
18 | 0.000000
19 | 0.000000
20 | 1.000000
21 | -0.000000
22 | 214896290070074160000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.000000
23 | 1144398331246043300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.000000
24 | 0.000000
25 | 0.000000
26 | -0.000000
27 | 0.000000
28 | 0.000000
29 | 0.000000
30 | 0.000000
31 | -0.000000
32 | SPHEROID_NAME: WGS 84
33 | DATUM_NAME: WGS 84
34 | SEMI_MAJOR_AXIS: 6378137.000000
35 | SEMI_MINOR_AXIS: 6356752.314245
36 | E_SQUARED: 0.006694
37 | RADIUS: 6371007.180918
38 |
--------------------------------------------------------------------------------
/utils.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import
2 | from __future__ import division
3 | from __future__ import print_function
4 | import numpy as np
5 | import matplotlib.pyplot as plt
6 | from osgeo import gdal
7 | from PIL import Image
8 | import array
9 | import sys
10 | import os
11 |
12 |
13 |
14 | # Reading Header file
15 | def hdr_read(path):
16 | row = 0
17 | col = 0
18 | bands = 0
19 | datatype = None
20 | with open(path, "r") as f:
21 | for l in f:
22 | k = l.split()
23 | if k[0] == "BANDS:":
24 | bands = k[1]
25 | elif k[0] == 'ROWS:':
26 | row = k[1]
27 | elif k[0] == 'COLS:':
28 | col = k[1]
29 | elif k[0] == 'DATATYPE:':
30 | datatype = k[1]
31 | mul, D_type = (255, 'uint8') if datatype == 'U8' else ((2**16-1), 'U16')
32 | print(mul, D_type)
33 | row = int(row)
34 | col = int(col)
35 | bands = int(bands)
36 | return row, col, bands, datatype
37 |
38 |
39 |
40 | # Reading Image file
41 | def ReadBilFile(bil,bands,pixels):
42 | extract_band = 1
43 | image = np.zeros([pixels, bands], dtype=np.uint16)
44 | gdal.GetDriverByName('EHdr').Register()
45 | img = gdal.Open(bil)
46 | while bands >= extract_band:
47 | bandx = img.GetRasterBand(extract_band)
48 | datax = bandx.ReadAsArray()
49 | temp = datax
50 | store = temp.reshape(pixels)
51 | for i in range(pixels):
52 | image[i][extract_band - 1] = store[i]
53 | extract_band = extract_band + 1
54 | return image
55 |
56 |
57 |
58 | # Returns a numpy array after thresholding
59 | def thresholding(Y, threshold):
60 | for i in range (Y.shape[0]):
61 | if(Y[i, :] < threshold):
62 | Y[i, :] = 0
63 | else:
64 | Y[i, :] = Y[i, :]
65 | return Y
66 |
67 |
68 |
69 | # Returns a numoy array after linear thretching its pixels
70 | def linear_stretch(y_test):
71 | minima = np.amin(y_test)
72 | maxima = np.amax(y_test)
73 | den = maxima-minima
74 | Y = ((y_test-minima)/ den)*(2**8 - 1)
75 | return(Y)
76 |
77 |
78 |
79 | # Takes matrix, no. of rows/col, and name with which image is to be saved
80 | # Returns a display on screen and saves the image with the given name
81 | def display_save_image(y, row, col, name):
82 | img = y.reshape(row, col)
83 | plt.imshow(img)
84 | plt.show()
85 | plt.savefig(name + '.png')
86 |
87 |
88 |
89 | # SOFT CLASSIFIER
90 | def extract_membership(y, class_no):
91 | Y = y[:, class_no].reshape(y.shape[0], 1)
92 | return(Y)
93 |
94 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Hybrid CNN-RNN Model for Hyperspectral Satellite Image Classification
2 |
3 | Satellite image processing is one of the key research areas in the area of remote sensing. In hyperspectral satellite imaging information from across a wide range of electromagnetic spectrum is collected by satellites. The goal of Remote Sensing is to obtain the spectrum for each pixel in the image of a scene, with the purpose of terrain analysis and generation, topographic mapping.
4 |
5 | Traditional statistical approaches provides reasonable success in this field, but the efficiency is limited with respect to the robustness of results. The statistical approaches are parametric, based on an assumed statistical distribution and hence the efficiency and correctness of results closely correlates to the proximity of data to the assumed distribution. Today advancements in artificial intelligence have made autonomous, large scale analysis of imagery possible, now AI can be taught to process Satellite Imagery with a small degree of error.
6 |
7 | In the following model we use hybrid CNN- RNN model for classification of each pixel to its corresponding classes. Further the code is developed to classify pixels in accordance with soft as well as hard classification techniques.
8 | 1.) HARD CLASSIFICATION : A pixel strictly belongs to a single class.
9 | 2.) SOFT CLASSIFICATION : A pixel may belong to more than one class based on its membership value.
10 |
11 | ## Libraries used
12 | * Keras : Keras is an open-source neural-network library written in Python. Designed to enable fast experimentation with deep neural networks, it focuses on being user-friendly, modular, and extensible.
13 | * Tensorflow : TensorFlow is a free and open-source software library for dataflow and differentiable programming across a range of tasks. It is a symbolic math library, and is also used for machine learning applications such as neural networks.
14 | * GDAL : The Geospatial Data Abstraction Library is a computer software library for reading and writing raster and vector geospatial data formats, and is released under the permissive X/MIT style free software license by the Open Source Geospatial Foundation.
15 | * Pillow : Python Imaging Library is a free library for the Python programming language that adds support for opening, manipulating, and saving many different image file formats.
16 | * Tkinter : Tkinter is the standard GUI library for Python. Python when combined with Tkinter provides a fast and easy way to create GUI applications.
17 | * Pickle : The pickle module implements binary protocols for serializing and de-serializing a Python object structure. “Pickling” is the process whereby a Python object hierarchy is converted into a byte stream, and “unpickling” is the inverse operation, whereby a byte stream (from a binary file or bytes-like object) is converted back into an object hierarchy.
18 | * Numpy : NumPy is a library for the Python programming language, adding support for large, multi-dimensional arrays and matrices, along with a large collection of high-level mathematical functions to operate on these arrays.
19 | * Matplotlib : Matplotlib is a plotting library for the Python programming language and its numerical mathematics extension NumPy.
20 | ## Description
21 | The repository consists of following files and folders
22 | * Notebooks : It consists of two jupyter notebooks
23 | - Hybrid CNN- RNN Model
24 | - Classification Tool (Hybrid CNN- RNN Model)
25 | * utils.py : Contains the necessary functions used in the notebook
26 | * Dataset :
27 | - Header and Image file (subfebformosat2)
28 | - Training set of 6 classes
29 | * Results : Contain image files
30 | ## Results
31 |
32 | 
33 | HARD CLASSIFICATION
34 |
35 | 
36 | SOFT CLASSIFICATION
37 |
--------------------------------------------------------------------------------
/notebooks/Hybrid CNN- RNN Model.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# Hybrid CNN- RNN Model for Classification of Hyperspectral Satelite Images \n",
8 | "The following model uses hybrid CNN- RNN model for classification of each pixel to its corresponding classes. Further the code is developed to classify pixels in accordance with soft as well as hard classification techniques. \n",
9 | "1.) HARD CLASSIFICATION : A pixel strictly belongs to a single class. \n",
10 | "2.) SOFT CLASSIFICATION : A pixel may belong to more than one class based on its membership value. "
11 | ]
12 | },
13 | {
14 | "cell_type": "markdown",
15 | "metadata": {},
16 | "source": [
17 | "## Importing necessary libraries and supporting files \n",
18 | "NOTE - 'utils' is a supporting .py file which contains all the functions used in the notebook"
19 | ]
20 | },
21 | {
22 | "cell_type": "code",
23 | "execution_count": 13,
24 | "metadata": {},
25 | "outputs": [],
26 | "source": [
27 | "from __future__ import absolute_import\n",
28 | "from __future__ import division\n",
29 | "from __future__ import print_function\n",
30 | "import numpy as np\n",
31 | "import matplotlib.pyplot as plt\n",
32 | "from osgeo import gdal\n",
33 | "from keras.layers import Dense, Conv1D, Input, MaxPooling1D, Flatten, Dropout, LSTM\n",
34 | "from keras import Sequential\n",
35 | "from keras.utils import np_utils\n",
36 | "from PIL import Image\n",
37 | "import array\n",
38 | "import sys\n",
39 | "import os\n",
40 | "from utils import hdr_read, ReadBilFile, thresholding, linear_stretch, display_save_image, extract_membership\n",
41 | "seed = 7\n",
42 | "np.random.seed(seed)\n"
43 | ]
44 | },
45 | {
46 | "cell_type": "markdown",
47 | "metadata": {},
48 | "source": [
49 | "## User Defined Parameters - \n",
50 | "1.)Header File : Contains the information about the image file such as - Datatype, Number of Rows and Columns, Total number of bands etc \n",
51 | "2.)Image File : The information extracted from header file(with extension .hdr) is used to extract the hyperspectral image from the Image File \n",
52 | "3.)Training Data : Training data consists of the value of pixel from each band for a particular class \n",
53 | "4.)Epochs(model training) : Number of iterations required to train the model. A lower value of epochs may lead to underfitting while a very high value may lead to overfitting of dataset, thus the choise of epochs is a crusial factor \n",
54 | "5.)Selected class and Threshold value(soft classification)) : For the purpose of soft classification user needs to specify the threshold value (it acts as a limit, the pixels having values above that value are only classifies while pixels below it are assigned a NULL value) "
55 | ]
56 | },
57 | {
58 | "cell_type": "code",
59 | "execution_count": 14,
60 | "metadata": {},
61 | "outputs": [],
62 | "source": [
63 | "# User defined inputs\n",
64 | "header_name = r\"C:\\Users\\HP DV-6\\Desktop\\final_project\\subfebformosat2.hdr\"\n",
65 | "file_name = r\"C:\\Users\\HP DV-6\\Desktop\\final_project\\subfebformosat2\"\n",
66 | "\n",
67 | "directory = r'C:\\Users\\HP DV-6\\Desktop\\final_project\\Data'\n",
68 | "\n",
69 | "epoch = '50'\n",
70 | "\n",
71 | "threshold = '0.8'\n",
72 | "\n",
73 | "category = 'Clay'"
74 | ]
75 | },
76 | {
77 | "cell_type": "code",
78 | "execution_count": 15,
79 | "metadata": {},
80 | "outputs": [],
81 | "source": [
82 | "# The functions are used for the conversion of string to integer and float values\n",
83 | "# Further the directory path is corrected \n",
84 | "epoch = int(epoch)\n",
85 | "threshold = float(threshold)\n",
86 | "\n",
87 | "directory = directory.replace(os.sep, '/')\n",
88 | "directory = directory + '/'\n",
89 | "\n",
90 | "header_name = header_name.replace(os.sep, '/')\n",
91 | "\n",
92 | "file_name = file_name.replace(os.sep, '/')"
93 | ]
94 | },
95 | {
96 | "cell_type": "code",
97 | "execution_count": 16,
98 | "metadata": {},
99 | "outputs": [
100 | {
101 | "name": "stdout",
102 | "output_type": "stream",
103 | "text": [
104 | "255 uint8\n"
105 | ]
106 | }
107 | ],
108 | "source": [
109 | "row, col, bands, datatype = hdr_read(header_name)\n",
110 | "x_test = ReadBilFile(file_name, bands, row*col)\n",
111 | "x_test = x_test.reshape(row*col, bands, 1)\n",
112 | "x_test = x_test / 2**8-1\n",
113 | "\n",
114 | "y_test = np.zeros([row*col], dtype=np.uint8) #Each pixel will belong to one class, so total no. of outputs=rows*columns"
115 | ]
116 | },
117 | {
118 | "cell_type": "code",
119 | "execution_count": 17,
120 | "metadata": {},
121 | "outputs": [
122 | {
123 | "name": "stdout",
124 | "output_type": "stream",
125 | "text": [
126 | "Clay ==> 22\n",
127 | "Dalforest ==> 23\n",
128 | "EuFinal ==> 8\n",
129 | "Grassland ==> 27\n",
130 | "Water ==> 36\n",
131 | "Wheat ==> 27\n"
132 | ]
133 | }
134 | ],
135 | "source": [
136 | "items = os.listdir(directory)\n",
137 | "path = items\n",
138 | "c_c = len(path)\n",
139 | "c_l = {items[i] : i for i in range(0, len(items))}\n",
140 | "\n",
141 | "values = []\n",
142 | "clicks={}\n",
143 | "\n",
144 | "for address in path: # function to know the total number of clicks of each class\n",
145 | " with open(directory+address, \"rb\") as f:\n",
146 | " k = len(f.read())\n",
147 | " clicks[address] = (k // 2 // bands) if (k // 2 // bands) < 400 else (k // 2 // bands) // 4\n",
148 | " print('{} ==> {}'.format(address, clicks[address]))\n",
149 | "\n",
150 | "for address in path: # function (VALUES) returns the value of all the pixels (len(values) = total_clicks * 4)\n",
151 | " with open(directory+address, \"rb\") as f:\n",
152 | " b = array.array(\"H\")\n",
153 | " b.fromfile(f, clicks[address]*bands)\n",
154 | " if sys.byteorder == \"little\":\n",
155 | " b.byteswap()\n",
156 | " for v in b:\n",
157 | " values.append(v)"
158 | ]
159 | },
160 | {
161 | "cell_type": "code",
162 | "execution_count": 18,
163 | "metadata": {},
164 | "outputs": [],
165 | "source": [
166 | "# Creation of training set\n",
167 | "ll = (len(values)) # = total_clicks * 4\n",
168 | "rex = ll // bands # = total clicks\n",
169 | "\n",
170 | "\n",
171 | "# Features\n",
172 | "f_in = np.zeros([ll], dtype=np.uint8)\n",
173 | "x = 0\n",
174 | "for i in range(ll):\n",
175 | " f_in[x] = values[i]\n",
176 | " x += 1\n",
177 | " \n",
178 | "x_train = f_in.reshape(rex, bands)\n",
179 | "x_train = x_train / 2**8-1 # Normalising dataset to facilitate fast training\n",
180 | "\n",
181 | "# Labels\n",
182 | "y_train = np.zeros([rex], dtype=np.uint8)\n",
183 | "mark = 0 # Creating label file (Mark does bifurcation of each class)\n",
184 | "for add in path: # outer loop iterates over each class\n",
185 | " for i in range(clicks[add]): # Inner loop assigns 1, 2, 3 based on c_1 dictionary to each pixel location\n",
186 | " y_train[mark+i] = c_l[add]\n",
187 | " mark = mark + clicks[add]"
188 | ]
189 | },
190 | {
191 | "cell_type": "code",
192 | "execution_count": 19,
193 | "metadata": {},
194 | "outputs": [],
195 | "source": [
196 | "y_train = np_utils.to_categorical(y_train)\n",
197 | "y_test = np_utils.to_categorical(y_test)\n",
198 | "n_classes = c_c\n",
199 | "y_test_new = np.zeros([row * col, c_c], dtype=np.uint8)\n",
200 | "\n",
201 | "\n",
202 | "X = x_train.reshape(x_train.shape[0], bands, 1)"
203 | ]
204 | },
205 | {
206 | "cell_type": "markdown",
207 | "metadata": {},
208 | "source": [
209 | "## Structuring Model and defining model parameters\n",
210 | "KERAS FRAMEWORK is used for the implementation of the model. The model consists of successive 1 dimensional Convolution and LSTM layers followed by Max Pooling layers. \n",
211 | "Convolution Neural Network: Convolutional Neural Networks, or CNNs were originally designed to map image data to an output variable.\n",
212 | "They have proven so effective that they are the go-to method for any type of prediction problem involving image data as an input. More generally, CNNs work well with data that has a spatial relationship. \n",
213 | "Recurrent Neural Network: Recurrent Neural Networks, or RNNs, were designed to work with sequence prediction problems. RNNs in general and LSTMs in particular have received the most success when working with sequences of words and paragraphs, generally called natural language processing. However they can be used for variety of other aplications such as image processing as well"
214 | ]
215 | },
216 | {
217 | "cell_type": "code",
218 | "execution_count": 20,
219 | "metadata": {},
220 | "outputs": [],
221 | "source": [
222 | "model = Sequential()\n",
223 | "\n",
224 | "model.add(Conv1D(32, 4, activation='relu', padding='same', input_shape=(4, 1)))\n",
225 | "model.add(LSTM(32, return_sequences=True))\n",
226 | "model.add(MaxPooling1D(2))\n",
227 | "model.add(Conv1D(16, 8, activation=\"relu\", padding='same'))\n",
228 | "model.add(LSTM(64, return_sequences=True))\n",
229 | "model.add(MaxPooling1D(2))\n",
230 | "model.add(Conv1D(16, 8, activation=\"relu\", padding='same'))\n",
231 | "model.add(LSTM(128))\n",
232 | "model.add(Dense(n_classes, activation='sigmoid'))"
233 | ]
234 | },
235 | {
236 | "cell_type": "markdown",
237 | "metadata": {},
238 | "source": [
239 | "### Model compilation and summary"
240 | ]
241 | },
242 | {
243 | "cell_type": "code",
244 | "execution_count": 21,
245 | "metadata": {},
246 | "outputs": [
247 | {
248 | "name": "stdout",
249 | "output_type": "stream",
250 | "text": [
251 | "_________________________________________________________________\n",
252 | "Layer (type) Output Shape Param # \n",
253 | "=================================================================\n",
254 | "conv1d_4 (Conv1D) (None, 4, 32) 160 \n",
255 | "_________________________________________________________________\n",
256 | "lstm_4 (LSTM) (None, 4, 32) 8320 \n",
257 | "_________________________________________________________________\n",
258 | "max_pooling1d_3 (MaxPooling1 (None, 2, 32) 0 \n",
259 | "_________________________________________________________________\n",
260 | "conv1d_5 (Conv1D) (None, 2, 16) 4112 \n",
261 | "_________________________________________________________________\n",
262 | "lstm_5 (LSTM) (None, 2, 64) 20736 \n",
263 | "_________________________________________________________________\n",
264 | "max_pooling1d_4 (MaxPooling1 (None, 1, 64) 0 \n",
265 | "_________________________________________________________________\n",
266 | "conv1d_6 (Conv1D) (None, 1, 16) 8208 \n",
267 | "_________________________________________________________________\n",
268 | "lstm_6 (LSTM) (None, 128) 74240 \n",
269 | "_________________________________________________________________\n",
270 | "dense_2 (Dense) (None, 6) 774 \n",
271 | "=================================================================\n",
272 | "Total params: 116,550\n",
273 | "Trainable params: 116,550\n",
274 | "Non-trainable params: 0\n",
275 | "_________________________________________________________________\n"
276 | ]
277 | }
278 | ],
279 | "source": [
280 | "model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])\n",
281 | "model.summary()"
282 | ]
283 | },
284 | {
285 | "cell_type": "markdown",
286 | "metadata": {},
287 | "source": [
288 | "### Training the model"
289 | ]
290 | },
291 | {
292 | "cell_type": "code",
293 | "execution_count": 22,
294 | "metadata": {},
295 | "outputs": [
296 | {
297 | "name": "stdout",
298 | "output_type": "stream",
299 | "text": [
300 | "Epoch 1/50\n",
301 | "143/143 [==============================] - 6s 45ms/step - loss: 1.7908 - acc: 0.2448\n",
302 | "Epoch 2/50\n",
303 | "143/143 [==============================] - 0s 2ms/step - loss: 1.7872 - acc: 0.2517\n",
304 | "Epoch 3/50\n",
305 | "143/143 [==============================] - 0s 2ms/step - loss: 1.7827 - acc: 0.2517\n",
306 | "Epoch 4/50\n",
307 | "143/143 [==============================] - 0s 2ms/step - loss: 1.7694 - acc: 0.2517\n",
308 | "Epoch 5/50\n",
309 | "143/143 [==============================] - 0s 2ms/step - loss: 1.7414 - acc: 0.2517\n",
310 | "Epoch 6/50\n",
311 | "143/143 [==============================] - 0s 2ms/step - loss: 1.7119 - acc: 0.2517\n",
312 | "Epoch 7/50\n",
313 | "143/143 [==============================] - 0s 2ms/step - loss: 1.7009 - acc: 0.2517\n",
314 | "Epoch 8/50\n",
315 | "143/143 [==============================] - ETA: 0s - loss: 1.6771 - acc: 0.261 - 0s 2ms/step - loss: 1.6779 - acc: 0.2517\n",
316 | "Epoch 9/50\n",
317 | "143/143 [==============================] - 0s 2ms/step - loss: 1.6418 - acc: 0.2517\n",
318 | "Epoch 10/50\n",
319 | "143/143 [==============================] - 0s 2ms/step - loss: 1.5920 - acc: 0.2517\n",
320 | "Epoch 11/50\n",
321 | "143/143 [==============================] - 0s 2ms/step - loss: 1.5711 - acc: 0.3497\n",
322 | "Epoch 12/50\n",
323 | "143/143 [==============================] - 0s 2ms/step - loss: 1.5557 - acc: 0.4056\n",
324 | "Epoch 13/50\n",
325 | "143/143 [==============================] - 0s 2ms/step - loss: 1.5404 - acc: 0.4056\n",
326 | "Epoch 14/50\n",
327 | "143/143 [==============================] - 0s 2ms/step - loss: 1.5168 - acc: 0.4056\n",
328 | "Epoch 15/50\n",
329 | "143/143 [==============================] - 0s 2ms/step - loss: 1.4643 - acc: 0.4056\n",
330 | "Epoch 16/50\n",
331 | "143/143 [==============================] - 0s 2ms/step - loss: 1.3757 - acc: 0.4056\n",
332 | "Epoch 17/50\n",
333 | "143/143 [==============================] - 0s 2ms/step - loss: 1.2489 - acc: 0.4056\n",
334 | "Epoch 18/50\n",
335 | "143/143 [==============================] - 0s 2ms/step - loss: 1.1285 - acc: 0.4056\n",
336 | "Epoch 19/50\n",
337 | "143/143 [==============================] - 0s 2ms/step - loss: 1.0402 - acc: 0.4056\n",
338 | "Epoch 20/50\n",
339 | "143/143 [==============================] - 0s 2ms/step - loss: 0.9595 - acc: 0.4126\n",
340 | "Epoch 21/50\n",
341 | "143/143 [==============================] - 0s 2ms/step - loss: 0.8530 - acc: 0.5524\n",
342 | "Epoch 22/50\n",
343 | "143/143 [==============================] - 0s 2ms/step - loss: 0.7579 - acc: 0.7832A: 0s - loss: 0.7912 - acc: 0.79\n",
344 | "Epoch 23/50\n",
345 | "143/143 [==============================] - 0s 2ms/step - loss: 0.6705 - acc: 0.7552\n",
346 | "Epoch 24/50\n",
347 | "143/143 [==============================] - 0s 2ms/step - loss: 0.6076 - acc: 0.7692\n",
348 | "Epoch 25/50\n",
349 | "143/143 [==============================] - 0s 2ms/step - loss: 0.5725 - acc: 0.7552\n",
350 | "Epoch 26/50\n",
351 | "143/143 [==============================] - 0s 2ms/step - loss: 0.5272 - acc: 0.7552\n",
352 | "Epoch 27/50\n",
353 | "143/143 [==============================] - 0s 2ms/step - loss: 0.4996 - acc: 0.7552\n",
354 | "Epoch 28/50\n",
355 | "143/143 [==============================] - 0s 2ms/step - loss: 0.4748 - acc: 0.7552\n",
356 | "Epoch 29/50\n",
357 | "143/143 [==============================] - 0s 2ms/step - loss: 0.4528 - acc: 0.7552\n",
358 | "Epoch 30/50\n",
359 | "143/143 [==============================] - 0s 2ms/step - loss: 0.4332 - acc: 0.7552\n",
360 | "Epoch 31/50\n",
361 | "143/143 [==============================] - 0s 2ms/step - loss: 0.4209 - acc: 0.7552\n",
362 | "Epoch 32/50\n",
363 | "143/143 [==============================] - 0s 2ms/step - loss: 0.4071 - acc: 0.7552\n",
364 | "Epoch 33/50\n",
365 | "143/143 [==============================] - 0s 2ms/step - loss: 0.3947 - acc: 0.7552\n",
366 | "Epoch 34/50\n",
367 | "143/143 [==============================] - 0s 2ms/step - loss: 0.3765 - acc: 0.7552\n",
368 | "Epoch 35/50\n",
369 | "143/143 [==============================] - 0s 2ms/step - loss: 0.3726 - acc: 0.7692\n",
370 | "Epoch 36/50\n",
371 | "143/143 [==============================] - 0s 2ms/step - loss: 0.3584 - acc: 0.7762\n",
372 | "Epoch 37/50\n",
373 | "143/143 [==============================] - 0s 2ms/step - loss: 0.3408 - acc: 0.7972\n",
374 | "Epoch 38/50\n",
375 | "143/143 [==============================] - 0s 2ms/step - loss: 0.3344 - acc: 0.8042\n",
376 | "Epoch 39/50\n",
377 | "143/143 [==============================] - 0s 2ms/step - loss: 0.3259 - acc: 0.7902\n",
378 | "Epoch 40/50\n",
379 | "143/143 [==============================] - 0s 2ms/step - loss: 0.3869 - acc: 0.8322\n",
380 | "Epoch 41/50\n",
381 | "143/143 [==============================] - 0s 2ms/step - loss: 0.3753 - acc: 0.8462\n",
382 | "Epoch 42/50\n",
383 | "143/143 [==============================] - 0s 2ms/step - loss: 0.3337 - acc: 0.8671A: 0s - loss: 0.3728 - acc: 0.82\n",
384 | "Epoch 43/50\n",
385 | "143/143 [==============================] - 0s 2ms/step - loss: 0.3104 - acc: 0.9161\n",
386 | "Epoch 44/50\n",
387 | "143/143 [==============================] - 0s 2ms/step - loss: 0.2984 - acc: 0.9161\n",
388 | "Epoch 45/50\n",
389 | "143/143 [==============================] - 0s 2ms/step - loss: 0.2915 - acc: 0.9371\n",
390 | "Epoch 46/50\n",
391 | "143/143 [==============================] - 0s 2ms/step - loss: 0.2841 - acc: 0.9441\n",
392 | "Epoch 47/50\n",
393 | "143/143 [==============================] - 0s 2ms/step - loss: 0.2839 - acc: 0.9441\n",
394 | "Epoch 48/50\n",
395 | "143/143 [==============================] - ETA: 0s - loss: 0.2735 - acc: 0.938 - 0s 2ms/step - loss: 0.2650 - acc: 0.9441\n",
396 | "Epoch 49/50\n",
397 | "143/143 [==============================] - 0s 2ms/step - loss: 0.2484 - acc: 0.9441\n",
398 | "Epoch 50/50\n",
399 | "143/143 [==============================] - 0s 2ms/step - loss: 0.2392 - acc: 0.9441\n"
400 | ]
401 | }
402 | ],
403 | "source": [
404 | "history = model.fit(X, y_train, batch_size=10, epochs=epoch)"
405 | ]
406 | },
407 | {
408 | "cell_type": "markdown",
409 | "metadata": {},
410 | "source": [
411 | "## Hard Classification \n",
412 | "In hard classification each pixel belongs to one category only"
413 | ]
414 | },
415 | {
416 | "cell_type": "code",
417 | "execution_count": 23,
418 | "metadata": {},
419 | "outputs": [
420 | {
421 | "data": {
422 | "application/javascript": [
423 | "/* Put everything inside the global mpl namespace */\n",
424 | "window.mpl = {};\n",
425 | "\n",
426 | "\n",
427 | "mpl.get_websocket_type = function() {\n",
428 | " if (typeof(WebSocket) !== 'undefined') {\n",
429 | " return WebSocket;\n",
430 | " } else if (typeof(MozWebSocket) !== 'undefined') {\n",
431 | " return MozWebSocket;\n",
432 | " } else {\n",
433 | " alert('Your browser does not have WebSocket support. ' +\n",
434 | " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n",
435 | " 'Firefox 4 and 5 are also supported but you ' +\n",
436 | " 'have to enable WebSockets in about:config.');\n",
437 | " };\n",
438 | "}\n",
439 | "\n",
440 | "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n",
441 | " this.id = figure_id;\n",
442 | "\n",
443 | " this.ws = websocket;\n",
444 | "\n",
445 | " this.supports_binary = (this.ws.binaryType != undefined);\n",
446 | "\n",
447 | " if (!this.supports_binary) {\n",
448 | " var warnings = document.getElementById(\"mpl-warnings\");\n",
449 | " if (warnings) {\n",
450 | " warnings.style.display = 'block';\n",
451 | " warnings.textContent = (\n",
452 | " \"This browser does not support binary websocket messages. \" +\n",
453 | " \"Performance may be slow.\");\n",
454 | " }\n",
455 | " }\n",
456 | "\n",
457 | " this.imageObj = new Image();\n",
458 | "\n",
459 | " this.context = undefined;\n",
460 | " this.message = undefined;\n",
461 | " this.canvas = undefined;\n",
462 | " this.rubberband_canvas = undefined;\n",
463 | " this.rubberband_context = undefined;\n",
464 | " this.format_dropdown = undefined;\n",
465 | "\n",
466 | " this.image_mode = 'full';\n",
467 | "\n",
468 | " this.root = $('
');\n",
469 | " this._root_extra_style(this.root)\n",
470 | " this.root.attr('style', 'display: inline-block');\n",
471 | "\n",
472 | " $(parent_element).append(this.root);\n",
473 | "\n",
474 | " this._init_header(this);\n",
475 | " this._init_canvas(this);\n",
476 | " this._init_toolbar(this);\n",
477 | "\n",
478 | " var fig = this;\n",
479 | "\n",
480 | " this.waiting = false;\n",
481 | "\n",
482 | " this.ws.onopen = function () {\n",
483 | " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n",
484 | " fig.send_message(\"send_image_mode\", {});\n",
485 | " if (mpl.ratio != 1) {\n",
486 | " fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n",
487 | " }\n",
488 | " fig.send_message(\"refresh\", {});\n",
489 | " }\n",
490 | "\n",
491 | " this.imageObj.onload = function() {\n",
492 | " if (fig.image_mode == 'full') {\n",
493 | " // Full images could contain transparency (where diff images\n",
494 | " // almost always do), so we need to clear the canvas so that\n",
495 | " // there is no ghosting.\n",
496 | " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n",
497 | " }\n",
498 | " fig.context.drawImage(fig.imageObj, 0, 0);\n",
499 | " };\n",
500 | "\n",
501 | " this.imageObj.onunload = function() {\n",
502 | " fig.ws.close();\n",
503 | " }\n",
504 | "\n",
505 | " this.ws.onmessage = this._make_on_message_function(this);\n",
506 | "\n",
507 | " this.ondownload = ondownload;\n",
508 | "}\n",
509 | "\n",
510 | "mpl.figure.prototype._init_header = function() {\n",
511 | " var titlebar = $(\n",
512 | " '
');\n",
514 | " var titletext = $(\n",
515 | " '
');\n",
517 | " titlebar.append(titletext)\n",
518 | " this.root.append(titlebar);\n",
519 | " this.header = titletext[0];\n",
520 | "}\n",
521 | "\n",
522 | "\n",
523 | "\n",
524 | "mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n",
525 | "\n",
526 | "}\n",
527 | "\n",
528 | "\n",
529 | "mpl.figure.prototype._root_extra_style = function(canvas_div) {\n",
530 | "\n",
531 | "}\n",
532 | "\n",
533 | "mpl.figure.prototype._init_canvas = function() {\n",
534 | " var fig = this;\n",
535 | "\n",
536 | " var canvas_div = $('
');\n",
537 | "\n",
538 | " canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n",
539 | "\n",
540 | " function canvas_keyboard_event(event) {\n",
541 | " return fig.key_event(event, event['data']);\n",
542 | " }\n",
543 | "\n",
544 | " canvas_div.keydown('key_press', canvas_keyboard_event);\n",
545 | " canvas_div.keyup('key_release', canvas_keyboard_event);\n",
546 | " this.canvas_div = canvas_div\n",
547 | " this._canvas_extra_style(canvas_div)\n",
548 | " this.root.append(canvas_div);\n",
549 | "\n",
550 | " var canvas = $(' ');\n",
551 | " canvas.addClass('mpl-canvas');\n",
552 | " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n",
553 | "\n",
554 | " this.canvas = canvas[0];\n",
555 | " this.context = canvas[0].getContext(\"2d\");\n",
556 | "\n",
557 | " var backingStore = this.context.backingStorePixelRatio ||\n",
558 | "\tthis.context.webkitBackingStorePixelRatio ||\n",
559 | "\tthis.context.mozBackingStorePixelRatio ||\n",
560 | "\tthis.context.msBackingStorePixelRatio ||\n",
561 | "\tthis.context.oBackingStorePixelRatio ||\n",
562 | "\tthis.context.backingStorePixelRatio || 1;\n",
563 | "\n",
564 | " mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n",
565 | "\n",
566 | " var rubberband = $(' ');\n",
567 | " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n",
568 | "\n",
569 | " var pass_mouse_events = true;\n",
570 | "\n",
571 | " canvas_div.resizable({\n",
572 | " start: function(event, ui) {\n",
573 | " pass_mouse_events = false;\n",
574 | " },\n",
575 | " resize: function(event, ui) {\n",
576 | " fig.request_resize(ui.size.width, ui.size.height);\n",
577 | " },\n",
578 | " stop: function(event, ui) {\n",
579 | " pass_mouse_events = true;\n",
580 | " fig.request_resize(ui.size.width, ui.size.height);\n",
581 | " },\n",
582 | " });\n",
583 | "\n",
584 | " function mouse_event_fn(event) {\n",
585 | " if (pass_mouse_events)\n",
586 | " return fig.mouse_event(event, event['data']);\n",
587 | " }\n",
588 | "\n",
589 | " rubberband.mousedown('button_press', mouse_event_fn);\n",
590 | " rubberband.mouseup('button_release', mouse_event_fn);\n",
591 | " // Throttle sequential mouse events to 1 every 20ms.\n",
592 | " rubberband.mousemove('motion_notify', mouse_event_fn);\n",
593 | "\n",
594 | " rubberband.mouseenter('figure_enter', mouse_event_fn);\n",
595 | " rubberband.mouseleave('figure_leave', mouse_event_fn);\n",
596 | "\n",
597 | " canvas_div.on(\"wheel\", function (event) {\n",
598 | " event = event.originalEvent;\n",
599 | " event['data'] = 'scroll'\n",
600 | " if (event.deltaY < 0) {\n",
601 | " event.step = 1;\n",
602 | " } else {\n",
603 | " event.step = -1;\n",
604 | " }\n",
605 | " mouse_event_fn(event);\n",
606 | " });\n",
607 | "\n",
608 | " canvas_div.append(canvas);\n",
609 | " canvas_div.append(rubberband);\n",
610 | "\n",
611 | " this.rubberband = rubberband;\n",
612 | " this.rubberband_canvas = rubberband[0];\n",
613 | " this.rubberband_context = rubberband[0].getContext(\"2d\");\n",
614 | " this.rubberband_context.strokeStyle = \"#000000\";\n",
615 | "\n",
616 | " this._resize_canvas = function(width, height) {\n",
617 | " // Keep the size of the canvas, canvas container, and rubber band\n",
618 | " // canvas in synch.\n",
619 | " canvas_div.css('width', width)\n",
620 | " canvas_div.css('height', height)\n",
621 | "\n",
622 | " canvas.attr('width', width * mpl.ratio);\n",
623 | " canvas.attr('height', height * mpl.ratio);\n",
624 | " canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n",
625 | "\n",
626 | " rubberband.attr('width', width);\n",
627 | " rubberband.attr('height', height);\n",
628 | " }\n",
629 | "\n",
630 | " // Set the figure to an initial 600x600px, this will subsequently be updated\n",
631 | " // upon first draw.\n",
632 | " this._resize_canvas(600, 600);\n",
633 | "\n",
634 | " // Disable right mouse context menu.\n",
635 | " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n",
636 | " return false;\n",
637 | " });\n",
638 | "\n",
639 | " function set_focus () {\n",
640 | " canvas.focus();\n",
641 | " canvas_div.focus();\n",
642 | " }\n",
643 | "\n",
644 | " window.setTimeout(set_focus, 100);\n",
645 | "}\n",
646 | "\n",
647 | "mpl.figure.prototype._init_toolbar = function() {\n",
648 | " var fig = this;\n",
649 | "\n",
650 | " var nav_element = $('
');\n",
651 | " nav_element.attr('style', 'width: 100%');\n",
652 | " this.root.append(nav_element);\n",
653 | "\n",
654 | " // Define a callback function for later on.\n",
655 | " function toolbar_event(event) {\n",
656 | " return fig.toolbar_button_onclick(event['data']);\n",
657 | " }\n",
658 | " function toolbar_mouse_event(event) {\n",
659 | " return fig.toolbar_button_onmouseover(event['data']);\n",
660 | " }\n",
661 | "\n",
662 | " for(var toolbar_ind in mpl.toolbar_items) {\n",
663 | " var name = mpl.toolbar_items[toolbar_ind][0];\n",
664 | " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n",
665 | " var image = mpl.toolbar_items[toolbar_ind][2];\n",
666 | " var method_name = mpl.toolbar_items[toolbar_ind][3];\n",
667 | "\n",
668 | " if (!name) {\n",
669 | " // put a spacer in here.\n",
670 | " continue;\n",
671 | " }\n",
672 | " var button = $(' ');\n",
673 | " button.addClass('ui-button ui-widget ui-state-default ui-corner-all ' +\n",
674 | " 'ui-button-icon-only');\n",
675 | " button.attr('role', 'button');\n",
676 | " button.attr('aria-disabled', 'false');\n",
677 | " button.click(method_name, toolbar_event);\n",
678 | " button.mouseover(tooltip, toolbar_mouse_event);\n",
679 | "\n",
680 | " var icon_img = $(' ');\n",
681 | " icon_img.addClass('ui-button-icon-primary ui-icon');\n",
682 | " icon_img.addClass(image);\n",
683 | " icon_img.addClass('ui-corner-all');\n",
684 | "\n",
685 | " var tooltip_span = $(' ');\n",
686 | " tooltip_span.addClass('ui-button-text');\n",
687 | " tooltip_span.html(tooltip);\n",
688 | "\n",
689 | " button.append(icon_img);\n",
690 | " button.append(tooltip_span);\n",
691 | "\n",
692 | " nav_element.append(button);\n",
693 | " }\n",
694 | "\n",
695 | " var fmt_picker_span = $(' ');\n",
696 | "\n",
697 | " var fmt_picker = $(' ');\n",
698 | " fmt_picker.addClass('mpl-toolbar-option ui-widget ui-widget-content');\n",
699 | " fmt_picker_span.append(fmt_picker);\n",
700 | " nav_element.append(fmt_picker_span);\n",
701 | " this.format_dropdown = fmt_picker[0];\n",
702 | "\n",
703 | " for (var ind in mpl.extensions) {\n",
704 | " var fmt = mpl.extensions[ind];\n",
705 | " var option = $(\n",
706 | " ' ', {selected: fmt === mpl.default_extension}).html(fmt);\n",
707 | " fmt_picker.append(option);\n",
708 | " }\n",
709 | "\n",
710 | " // Add hover states to the ui-buttons\n",
711 | " $( \".ui-button\" ).hover(\n",
712 | " function() { $(this).addClass(\"ui-state-hover\");},\n",
713 | " function() { $(this).removeClass(\"ui-state-hover\");}\n",
714 | " );\n",
715 | "\n",
716 | " var status_bar = $('');\n",
717 | " nav_element.append(status_bar);\n",
718 | " this.message = status_bar[0];\n",
719 | "}\n",
720 | "\n",
721 | "mpl.figure.prototype.request_resize = function(x_pixels, y_pixels) {\n",
722 | " // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n",
723 | " // which will in turn request a refresh of the image.\n",
724 | " this.send_message('resize', {'width': x_pixels, 'height': y_pixels});\n",
725 | "}\n",
726 | "\n",
727 | "mpl.figure.prototype.send_message = function(type, properties) {\n",
728 | " properties['type'] = type;\n",
729 | " properties['figure_id'] = this.id;\n",
730 | " this.ws.send(JSON.stringify(properties));\n",
731 | "}\n",
732 | "\n",
733 | "mpl.figure.prototype.send_draw_message = function() {\n",
734 | " if (!this.waiting) {\n",
735 | " this.waiting = true;\n",
736 | " this.ws.send(JSON.stringify({type: \"draw\", figure_id: this.id}));\n",
737 | " }\n",
738 | "}\n",
739 | "\n",
740 | "\n",
741 | "mpl.figure.prototype.handle_save = function(fig, msg) {\n",
742 | " var format_dropdown = fig.format_dropdown;\n",
743 | " var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n",
744 | " fig.ondownload(fig, format);\n",
745 | "}\n",
746 | "\n",
747 | "\n",
748 | "mpl.figure.prototype.handle_resize = function(fig, msg) {\n",
749 | " var size = msg['size'];\n",
750 | " if (size[0] != fig.canvas.width || size[1] != fig.canvas.height) {\n",
751 | " fig._resize_canvas(size[0], size[1]);\n",
752 | " fig.send_message(\"refresh\", {});\n",
753 | " };\n",
754 | "}\n",
755 | "\n",
756 | "mpl.figure.prototype.handle_rubberband = function(fig, msg) {\n",
757 | " var x0 = msg['x0'] / mpl.ratio;\n",
758 | " var y0 = (fig.canvas.height - msg['y0']) / mpl.ratio;\n",
759 | " var x1 = msg['x1'] / mpl.ratio;\n",
760 | " var y1 = (fig.canvas.height - msg['y1']) / mpl.ratio;\n",
761 | " x0 = Math.floor(x0) + 0.5;\n",
762 | " y0 = Math.floor(y0) + 0.5;\n",
763 | " x1 = Math.floor(x1) + 0.5;\n",
764 | " y1 = Math.floor(y1) + 0.5;\n",
765 | " var min_x = Math.min(x0, x1);\n",
766 | " var min_y = Math.min(y0, y1);\n",
767 | " var width = Math.abs(x1 - x0);\n",
768 | " var height = Math.abs(y1 - y0);\n",
769 | "\n",
770 | " fig.rubberband_context.clearRect(\n",
771 | " 0, 0, fig.canvas.width, fig.canvas.height);\n",
772 | "\n",
773 | " fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n",
774 | "}\n",
775 | "\n",
776 | "mpl.figure.prototype.handle_figure_label = function(fig, msg) {\n",
777 | " // Updates the figure title.\n",
778 | " fig.header.textContent = msg['label'];\n",
779 | "}\n",
780 | "\n",
781 | "mpl.figure.prototype.handle_cursor = function(fig, msg) {\n",
782 | " var cursor = msg['cursor'];\n",
783 | " switch(cursor)\n",
784 | " {\n",
785 | " case 0:\n",
786 | " cursor = 'pointer';\n",
787 | " break;\n",
788 | " case 1:\n",
789 | " cursor = 'default';\n",
790 | " break;\n",
791 | " case 2:\n",
792 | " cursor = 'crosshair';\n",
793 | " break;\n",
794 | " case 3:\n",
795 | " cursor = 'move';\n",
796 | " break;\n",
797 | " }\n",
798 | " fig.rubberband_canvas.style.cursor = cursor;\n",
799 | "}\n",
800 | "\n",
801 | "mpl.figure.prototype.handle_message = function(fig, msg) {\n",
802 | " fig.message.textContent = msg['message'];\n",
803 | "}\n",
804 | "\n",
805 | "mpl.figure.prototype.handle_draw = function(fig, msg) {\n",
806 | " // Request the server to send over a new figure.\n",
807 | " fig.send_draw_message();\n",
808 | "}\n",
809 | "\n",
810 | "mpl.figure.prototype.handle_image_mode = function(fig, msg) {\n",
811 | " fig.image_mode = msg['mode'];\n",
812 | "}\n",
813 | "\n",
814 | "mpl.figure.prototype.updated_canvas_event = function() {\n",
815 | " // Called whenever the canvas gets updated.\n",
816 | " this.send_message(\"ack\", {});\n",
817 | "}\n",
818 | "\n",
819 | "// A function to construct a web socket function for onmessage handling.\n",
820 | "// Called in the figure constructor.\n",
821 | "mpl.figure.prototype._make_on_message_function = function(fig) {\n",
822 | " return function socket_on_message(evt) {\n",
823 | " if (evt.data instanceof Blob) {\n",
824 | " /* FIXME: We get \"Resource interpreted as Image but\n",
825 | " * transferred with MIME type text/plain:\" errors on\n",
826 | " * Chrome. But how to set the MIME type? It doesn't seem\n",
827 | " * to be part of the websocket stream */\n",
828 | " evt.data.type = \"image/png\";\n",
829 | "\n",
830 | " /* Free the memory for the previous frames */\n",
831 | " if (fig.imageObj.src) {\n",
832 | " (window.URL || window.webkitURL).revokeObjectURL(\n",
833 | " fig.imageObj.src);\n",
834 | " }\n",
835 | "\n",
836 | " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
837 | " evt.data);\n",
838 | " fig.updated_canvas_event();\n",
839 | " fig.waiting = false;\n",
840 | " return;\n",
841 | " }\n",
842 | " else if (typeof evt.data === 'string' && evt.data.slice(0, 21) == \"data:image/png;base64\") {\n",
843 | " fig.imageObj.src = evt.data;\n",
844 | " fig.updated_canvas_event();\n",
845 | " fig.waiting = false;\n",
846 | " return;\n",
847 | " }\n",
848 | "\n",
849 | " var msg = JSON.parse(evt.data);\n",
850 | " var msg_type = msg['type'];\n",
851 | "\n",
852 | " // Call the \"handle_{type}\" callback, which takes\n",
853 | " // the figure and JSON message as its only arguments.\n",
854 | " try {\n",
855 | " var callback = fig[\"handle_\" + msg_type];\n",
856 | " } catch (e) {\n",
857 | " console.log(\"No handler for the '\" + msg_type + \"' message type: \", msg);\n",
858 | " return;\n",
859 | " }\n",
860 | "\n",
861 | " if (callback) {\n",
862 | " try {\n",
863 | " // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n",
864 | " callback(fig, msg);\n",
865 | " } catch (e) {\n",
866 | " console.log(\"Exception inside the 'handler_\" + msg_type + \"' callback:\", e, e.stack, msg);\n",
867 | " }\n",
868 | " }\n",
869 | " };\n",
870 | "}\n",
871 | "\n",
872 | "// from http://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n",
873 | "mpl.findpos = function(e) {\n",
874 | " //this section is from http://www.quirksmode.org/js/events_properties.html\n",
875 | " var targ;\n",
876 | " if (!e)\n",
877 | " e = window.event;\n",
878 | " if (e.target)\n",
879 | " targ = e.target;\n",
880 | " else if (e.srcElement)\n",
881 | " targ = e.srcElement;\n",
882 | " if (targ.nodeType == 3) // defeat Safari bug\n",
883 | " targ = targ.parentNode;\n",
884 | "\n",
885 | " // jQuery normalizes the pageX and pageY\n",
886 | " // pageX,Y are the mouse positions relative to the document\n",
887 | " // offset() returns the position of the element relative to the document\n",
888 | " var x = e.pageX - $(targ).offset().left;\n",
889 | " var y = e.pageY - $(targ).offset().top;\n",
890 | "\n",
891 | " return {\"x\": x, \"y\": y};\n",
892 | "};\n",
893 | "\n",
894 | "/*\n",
895 | " * return a copy of an object with only non-object keys\n",
896 | " * we need this to avoid circular references\n",
897 | " * http://stackoverflow.com/a/24161582/3208463\n",
898 | " */\n",
899 | "function simpleKeys (original) {\n",
900 | " return Object.keys(original).reduce(function (obj, key) {\n",
901 | " if (typeof original[key] !== 'object')\n",
902 | " obj[key] = original[key]\n",
903 | " return obj;\n",
904 | " }, {});\n",
905 | "}\n",
906 | "\n",
907 | "mpl.figure.prototype.mouse_event = function(event, name) {\n",
908 | " var canvas_pos = mpl.findpos(event)\n",
909 | "\n",
910 | " if (name === 'button_press')\n",
911 | " {\n",
912 | " this.canvas.focus();\n",
913 | " this.canvas_div.focus();\n",
914 | " }\n",
915 | "\n",
916 | " var x = canvas_pos.x * mpl.ratio;\n",
917 | " var y = canvas_pos.y * mpl.ratio;\n",
918 | "\n",
919 | " this.send_message(name, {x: x, y: y, button: event.button,\n",
920 | " step: event.step,\n",
921 | " guiEvent: simpleKeys(event)});\n",
922 | "\n",
923 | " /* This prevents the web browser from automatically changing to\n",
924 | " * the text insertion cursor when the button is pressed. We want\n",
925 | " * to control all of the cursor setting manually through the\n",
926 | " * 'cursor' event from matplotlib */\n",
927 | " event.preventDefault();\n",
928 | " return false;\n",
929 | "}\n",
930 | "\n",
931 | "mpl.figure.prototype._key_event_extra = function(event, name) {\n",
932 | " // Handle any extra behaviour associated with a key event\n",
933 | "}\n",
934 | "\n",
935 | "mpl.figure.prototype.key_event = function(event, name) {\n",
936 | "\n",
937 | " // Prevent repeat events\n",
938 | " if (name == 'key_press')\n",
939 | " {\n",
940 | " if (event.which === this._key)\n",
941 | " return;\n",
942 | " else\n",
943 | " this._key = event.which;\n",
944 | " }\n",
945 | " if (name == 'key_release')\n",
946 | " this._key = null;\n",
947 | "\n",
948 | " var value = '';\n",
949 | " if (event.ctrlKey && event.which != 17)\n",
950 | " value += \"ctrl+\";\n",
951 | " if (event.altKey && event.which != 18)\n",
952 | " value += \"alt+\";\n",
953 | " if (event.shiftKey && event.which != 16)\n",
954 | " value += \"shift+\";\n",
955 | "\n",
956 | " value += 'k';\n",
957 | " value += event.which.toString();\n",
958 | "\n",
959 | " this._key_event_extra(event, name);\n",
960 | "\n",
961 | " this.send_message(name, {key: value,\n",
962 | " guiEvent: simpleKeys(event)});\n",
963 | " return false;\n",
964 | "}\n",
965 | "\n",
966 | "mpl.figure.prototype.toolbar_button_onclick = function(name) {\n",
967 | " if (name == 'download') {\n",
968 | " this.handle_save(this, null);\n",
969 | " } else {\n",
970 | " this.send_message(\"toolbar_button\", {name: name});\n",
971 | " }\n",
972 | "};\n",
973 | "\n",
974 | "mpl.figure.prototype.toolbar_button_onmouseover = function(tooltip) {\n",
975 | " this.message.textContent = tooltip;\n",
976 | "};\n",
977 | "mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n",
978 | "\n",
979 | "mpl.extensions = [\"eps\", \"jpeg\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n",
980 | "\n",
981 | "mpl.default_extension = \"png\";var comm_websocket_adapter = function(comm) {\n",
982 | " // Create a \"websocket\"-like object which calls the given IPython comm\n",
983 | " // object with the appropriate methods. Currently this is a non binary\n",
984 | " // socket, so there is still some room for performance tuning.\n",
985 | " var ws = {};\n",
986 | "\n",
987 | " ws.close = function() {\n",
988 | " comm.close()\n",
989 | " };\n",
990 | " ws.send = function(m) {\n",
991 | " //console.log('sending', m);\n",
992 | " comm.send(m);\n",
993 | " };\n",
994 | " // Register the callback with on_msg.\n",
995 | " comm.on_msg(function(msg) {\n",
996 | " //console.log('receiving', msg['content']['data'], msg);\n",
997 | " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
998 | " ws.onmessage(msg['content']['data'])\n",
999 | " });\n",
1000 | " return ws;\n",
1001 | "}\n",
1002 | "\n",
1003 | "mpl.mpl_figure_comm = function(comm, msg) {\n",
1004 | " // This is the function which gets called when the mpl process\n",
1005 | " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
1006 | "\n",
1007 | " var id = msg.content.data.id;\n",
1008 | " // Get hold of the div created by the display call when the Comm\n",
1009 | " // socket was opened in Python.\n",
1010 | " var element = $(\"#\" + id);\n",
1011 | " var ws_proxy = comm_websocket_adapter(comm)\n",
1012 | "\n",
1013 | " function ondownload(figure, format) {\n",
1014 | " window.open(figure.imageObj.src);\n",
1015 | " }\n",
1016 | "\n",
1017 | " var fig = new mpl.figure(id, ws_proxy,\n",
1018 | " ondownload,\n",
1019 | " element.get(0));\n",
1020 | "\n",
1021 | " // Call onopen now - mpl needs it, as it is assuming we've passed it a real\n",
1022 | " // web socket which is closed, not our websocket->open comm proxy.\n",
1023 | " ws_proxy.onopen();\n",
1024 | "\n",
1025 | " fig.parent_element = element.get(0);\n",
1026 | " fig.cell_info = mpl.find_output_cell(\"
\");\n",
1027 | " if (!fig.cell_info) {\n",
1028 | " console.error(\"Failed to find cell for figure\", id, fig);\n",
1029 | " return;\n",
1030 | " }\n",
1031 | "\n",
1032 | " var output_index = fig.cell_info[2]\n",
1033 | " var cell = fig.cell_info[0];\n",
1034 | "\n",
1035 | "};\n",
1036 | "\n",
1037 | "mpl.figure.prototype.handle_close = function(fig, msg) {\n",
1038 | " var width = fig.canvas.width/mpl.ratio\n",
1039 | " fig.root.unbind('remove')\n",
1040 | "\n",
1041 | " // Update the output cell to use the data from the current canvas.\n",
1042 | " fig.push_to_output();\n",
1043 | " var dataURL = fig.canvas.toDataURL();\n",
1044 | " // Re-enable the keyboard manager in IPython - without this line, in FF,\n",
1045 | " // the notebook keyboard shortcuts fail.\n",
1046 | " IPython.keyboard_manager.enable()\n",
1047 | " $(fig.parent_element).html(' ');\n",
1048 | " fig.close_ws(fig, msg);\n",
1049 | "}\n",
1050 | "\n",
1051 | "mpl.figure.prototype.close_ws = function(fig, msg){\n",
1052 | " fig.send_message('closing', msg);\n",
1053 | " // fig.ws.close()\n",
1054 | "}\n",
1055 | "\n",
1056 | "mpl.figure.prototype.push_to_output = function(remove_interactive) {\n",
1057 | " // Turn the data on the canvas into data in the output cell.\n",
1058 | " var width = this.canvas.width/mpl.ratio\n",
1059 | " var dataURL = this.canvas.toDataURL();\n",
1060 | " this.cell_info[1]['text/html'] = ' ';\n",
1061 | "}\n",
1062 | "\n",
1063 | "mpl.figure.prototype.updated_canvas_event = function() {\n",
1064 | " // Tell IPython that the notebook contents must change.\n",
1065 | " IPython.notebook.set_dirty(true);\n",
1066 | " this.send_message(\"ack\", {});\n",
1067 | " var fig = this;\n",
1068 | " // Wait a second, then push the new image to the DOM so\n",
1069 | " // that it is saved nicely (might be nice to debounce this).\n",
1070 | " setTimeout(function () { fig.push_to_output() }, 1000);\n",
1071 | "}\n",
1072 | "\n",
1073 | "mpl.figure.prototype._init_toolbar = function() {\n",
1074 | " var fig = this;\n",
1075 | "\n",
1076 | " var nav_element = $('
');\n",
1077 | " nav_element.attr('style', 'width: 100%');\n",
1078 | " this.root.append(nav_element);\n",
1079 | "\n",
1080 | " // Define a callback function for later on.\n",
1081 | " function toolbar_event(event) {\n",
1082 | " return fig.toolbar_button_onclick(event['data']);\n",
1083 | " }\n",
1084 | " function toolbar_mouse_event(event) {\n",
1085 | " return fig.toolbar_button_onmouseover(event['data']);\n",
1086 | " }\n",
1087 | "\n",
1088 | " for(var toolbar_ind in mpl.toolbar_items){\n",
1089 | " var name = mpl.toolbar_items[toolbar_ind][0];\n",
1090 | " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n",
1091 | " var image = mpl.toolbar_items[toolbar_ind][2];\n",
1092 | " var method_name = mpl.toolbar_items[toolbar_ind][3];\n",
1093 | "\n",
1094 | " if (!name) { continue; };\n",
1095 | "\n",
1096 | " var button = $(' ');\n",
1097 | " button.click(method_name, toolbar_event);\n",
1098 | " button.mouseover(tooltip, toolbar_mouse_event);\n",
1099 | " nav_element.append(button);\n",
1100 | " }\n",
1101 | "\n",
1102 | " // Add the status bar.\n",
1103 | " var status_bar = $(' ');\n",
1104 | " nav_element.append(status_bar);\n",
1105 | " this.message = status_bar[0];\n",
1106 | "\n",
1107 | " // Add the close button to the window.\n",
1108 | " var buttongrp = $('
');\n",
1109 | " var button = $(' ');\n",
1110 | " button.click(function (evt) { fig.handle_close(fig, {}); } );\n",
1111 | " button.mouseover('Stop Interaction', toolbar_mouse_event);\n",
1112 | " buttongrp.append(button);\n",
1113 | " var titlebar = this.root.find($('.ui-dialog-titlebar'));\n",
1114 | " titlebar.prepend(buttongrp);\n",
1115 | "}\n",
1116 | "\n",
1117 | "mpl.figure.prototype._root_extra_style = function(el){\n",
1118 | " var fig = this\n",
1119 | " el.on(\"remove\", function(){\n",
1120 | "\tfig.close_ws(fig, {});\n",
1121 | " });\n",
1122 | "}\n",
1123 | "\n",
1124 | "mpl.figure.prototype._canvas_extra_style = function(el){\n",
1125 | " // this is important to make the div 'focusable\n",
1126 | " el.attr('tabindex', 0)\n",
1127 | " // reach out to IPython and tell the keyboard manager to turn it's self\n",
1128 | " // off when our div gets focus\n",
1129 | "\n",
1130 | " // location in version 3\n",
1131 | " if (IPython.notebook.keyboard_manager) {\n",
1132 | " IPython.notebook.keyboard_manager.register_events(el);\n",
1133 | " }\n",
1134 | " else {\n",
1135 | " // location in version 2\n",
1136 | " IPython.keyboard_manager.register_events(el);\n",
1137 | " }\n",
1138 | "\n",
1139 | "}\n",
1140 | "\n",
1141 | "mpl.figure.prototype._key_event_extra = function(event, name) {\n",
1142 | " var manager = IPython.notebook.keyboard_manager;\n",
1143 | " if (!manager)\n",
1144 | " manager = IPython.keyboard_manager;\n",
1145 | "\n",
1146 | " // Check for shift+enter\n",
1147 | " if (event.shiftKey && event.which == 13) {\n",
1148 | " this.canvas_div.blur();\n",
1149 | " event.shiftKey = false;\n",
1150 | " // Send a \"J\" for go to next cell\n",
1151 | " event.which = 74;\n",
1152 | " event.keyCode = 74;\n",
1153 | " manager.command_mode();\n",
1154 | " manager.handle_keydown(event);\n",
1155 | " }\n",
1156 | "}\n",
1157 | "\n",
1158 | "mpl.figure.prototype.handle_save = function(fig, msg) {\n",
1159 | " fig.ondownload(fig, null);\n",
1160 | "}\n",
1161 | "\n",
1162 | "\n",
1163 | "mpl.find_output_cell = function(html_output) {\n",
1164 | " // Return the cell and output element which can be found *uniquely* in the notebook.\n",
1165 | " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n",
1166 | " // IPython event is triggered only after the cells have been serialised, which for\n",
1167 | " // our purposes (turning an active figure into a static one), is too late.\n",
1168 | " var cells = IPython.notebook.get_cells();\n",
1169 | " var ncells = cells.length;\n",
1170 | " for (var i=0; i= 3 moved mimebundle to data attribute of output\n",
1177 | " data = data.data;\n",
1178 | " }\n",
1179 | " if (data['text/html'] == html_output) {\n",
1180 | " return [cell, data, j];\n",
1181 | " }\n",
1182 | " }\n",
1183 | " }\n",
1184 | " }\n",
1185 | "}\n",
1186 | "\n",
1187 | "// Register the function which deals with the matplotlib target/channel.\n",
1188 | "// The kernel may be null if the page has been refreshed.\n",
1189 | "if (IPython.notebook.kernel != null) {\n",
1190 | " IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n",
1191 | "}\n"
1192 | ],
1193 | "text/plain": [
1194 | ""
1195 | ]
1196 | },
1197 | "metadata": {},
1198 | "output_type": "display_data"
1199 | },
1200 | {
1201 | "data": {
1202 | "text/html": [
1203 | " "
1204 | ],
1205 | "text/plain": [
1206 | ""
1207 | ]
1208 | },
1209 | "metadata": {},
1210 | "output_type": "display_data"
1211 | }
1212 | ],
1213 | "source": [
1214 | "%matplotlib notebook\n",
1215 | "y_test_new = model.predict(x_test, batch_size=50)\n",
1216 | "y_test1 = np.argmax(y_test_new, axis=1)\n",
1217 | "\n",
1218 | "display_save_image(y_test1, row, col, 'hard_classified')"
1219 | ]
1220 | },
1221 | {
1222 | "cell_type": "markdown",
1223 | "metadata": {},
1224 | "source": [
1225 | "## Soft Classification \n",
1226 | "In soft classification a pixel may belong to more than one class based on their membership values."
1227 | ]
1228 | },
1229 | {
1230 | "cell_type": "code",
1231 | "execution_count": 24,
1232 | "metadata": {},
1233 | "outputs": [
1234 | {
1235 | "name": "stdout",
1236 | "output_type": "stream",
1237 | "text": [
1238 | "Class number: 0\n"
1239 | ]
1240 | },
1241 | {
1242 | "data": {
1243 | "application/javascript": [
1244 | "/* Put everything inside the global mpl namespace */\n",
1245 | "window.mpl = {};\n",
1246 | "\n",
1247 | "\n",
1248 | "mpl.get_websocket_type = function() {\n",
1249 | " if (typeof(WebSocket) !== 'undefined') {\n",
1250 | " return WebSocket;\n",
1251 | " } else if (typeof(MozWebSocket) !== 'undefined') {\n",
1252 | " return MozWebSocket;\n",
1253 | " } else {\n",
1254 | " alert('Your browser does not have WebSocket support. ' +\n",
1255 | " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n",
1256 | " 'Firefox 4 and 5 are also supported but you ' +\n",
1257 | " 'have to enable WebSockets in about:config.');\n",
1258 | " };\n",
1259 | "}\n",
1260 | "\n",
1261 | "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n",
1262 | " this.id = figure_id;\n",
1263 | "\n",
1264 | " this.ws = websocket;\n",
1265 | "\n",
1266 | " this.supports_binary = (this.ws.binaryType != undefined);\n",
1267 | "\n",
1268 | " if (!this.supports_binary) {\n",
1269 | " var warnings = document.getElementById(\"mpl-warnings\");\n",
1270 | " if (warnings) {\n",
1271 | " warnings.style.display = 'block';\n",
1272 | " warnings.textContent = (\n",
1273 | " \"This browser does not support binary websocket messages. \" +\n",
1274 | " \"Performance may be slow.\");\n",
1275 | " }\n",
1276 | " }\n",
1277 | "\n",
1278 | " this.imageObj = new Image();\n",
1279 | "\n",
1280 | " this.context = undefined;\n",
1281 | " this.message = undefined;\n",
1282 | " this.canvas = undefined;\n",
1283 | " this.rubberband_canvas = undefined;\n",
1284 | " this.rubberband_context = undefined;\n",
1285 | " this.format_dropdown = undefined;\n",
1286 | "\n",
1287 | " this.image_mode = 'full';\n",
1288 | "\n",
1289 | " this.root = $('
');\n",
1290 | " this._root_extra_style(this.root)\n",
1291 | " this.root.attr('style', 'display: inline-block');\n",
1292 | "\n",
1293 | " $(parent_element).append(this.root);\n",
1294 | "\n",
1295 | " this._init_header(this);\n",
1296 | " this._init_canvas(this);\n",
1297 | " this._init_toolbar(this);\n",
1298 | "\n",
1299 | " var fig = this;\n",
1300 | "\n",
1301 | " this.waiting = false;\n",
1302 | "\n",
1303 | " this.ws.onopen = function () {\n",
1304 | " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n",
1305 | " fig.send_message(\"send_image_mode\", {});\n",
1306 | " if (mpl.ratio != 1) {\n",
1307 | " fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n",
1308 | " }\n",
1309 | " fig.send_message(\"refresh\", {});\n",
1310 | " }\n",
1311 | "\n",
1312 | " this.imageObj.onload = function() {\n",
1313 | " if (fig.image_mode == 'full') {\n",
1314 | " // Full images could contain transparency (where diff images\n",
1315 | " // almost always do), so we need to clear the canvas so that\n",
1316 | " // there is no ghosting.\n",
1317 | " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n",
1318 | " }\n",
1319 | " fig.context.drawImage(fig.imageObj, 0, 0);\n",
1320 | " };\n",
1321 | "\n",
1322 | " this.imageObj.onunload = function() {\n",
1323 | " fig.ws.close();\n",
1324 | " }\n",
1325 | "\n",
1326 | " this.ws.onmessage = this._make_on_message_function(this);\n",
1327 | "\n",
1328 | " this.ondownload = ondownload;\n",
1329 | "}\n",
1330 | "\n",
1331 | "mpl.figure.prototype._init_header = function() {\n",
1332 | " var titlebar = $(\n",
1333 | " '
');\n",
1335 | " var titletext = $(\n",
1336 | " '
');\n",
1338 | " titlebar.append(titletext)\n",
1339 | " this.root.append(titlebar);\n",
1340 | " this.header = titletext[0];\n",
1341 | "}\n",
1342 | "\n",
1343 | "\n",
1344 | "\n",
1345 | "mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n",
1346 | "\n",
1347 | "}\n",
1348 | "\n",
1349 | "\n",
1350 | "mpl.figure.prototype._root_extra_style = function(canvas_div) {\n",
1351 | "\n",
1352 | "}\n",
1353 | "\n",
1354 | "mpl.figure.prototype._init_canvas = function() {\n",
1355 | " var fig = this;\n",
1356 | "\n",
1357 | " var canvas_div = $('
');\n",
1358 | "\n",
1359 | " canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n",
1360 | "\n",
1361 | " function canvas_keyboard_event(event) {\n",
1362 | " return fig.key_event(event, event['data']);\n",
1363 | " }\n",
1364 | "\n",
1365 | " canvas_div.keydown('key_press', canvas_keyboard_event);\n",
1366 | " canvas_div.keyup('key_release', canvas_keyboard_event);\n",
1367 | " this.canvas_div = canvas_div\n",
1368 | " this._canvas_extra_style(canvas_div)\n",
1369 | " this.root.append(canvas_div);\n",
1370 | "\n",
1371 | " var canvas = $(' ');\n",
1372 | " canvas.addClass('mpl-canvas');\n",
1373 | " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n",
1374 | "\n",
1375 | " this.canvas = canvas[0];\n",
1376 | " this.context = canvas[0].getContext(\"2d\");\n",
1377 | "\n",
1378 | " var backingStore = this.context.backingStorePixelRatio ||\n",
1379 | "\tthis.context.webkitBackingStorePixelRatio ||\n",
1380 | "\tthis.context.mozBackingStorePixelRatio ||\n",
1381 | "\tthis.context.msBackingStorePixelRatio ||\n",
1382 | "\tthis.context.oBackingStorePixelRatio ||\n",
1383 | "\tthis.context.backingStorePixelRatio || 1;\n",
1384 | "\n",
1385 | " mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n",
1386 | "\n",
1387 | " var rubberband = $(' ');\n",
1388 | " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n",
1389 | "\n",
1390 | " var pass_mouse_events = true;\n",
1391 | "\n",
1392 | " canvas_div.resizable({\n",
1393 | " start: function(event, ui) {\n",
1394 | " pass_mouse_events = false;\n",
1395 | " },\n",
1396 | " resize: function(event, ui) {\n",
1397 | " fig.request_resize(ui.size.width, ui.size.height);\n",
1398 | " },\n",
1399 | " stop: function(event, ui) {\n",
1400 | " pass_mouse_events = true;\n",
1401 | " fig.request_resize(ui.size.width, ui.size.height);\n",
1402 | " },\n",
1403 | " });\n",
1404 | "\n",
1405 | " function mouse_event_fn(event) {\n",
1406 | " if (pass_mouse_events)\n",
1407 | " return fig.mouse_event(event, event['data']);\n",
1408 | " }\n",
1409 | "\n",
1410 | " rubberband.mousedown('button_press', mouse_event_fn);\n",
1411 | " rubberband.mouseup('button_release', mouse_event_fn);\n",
1412 | " // Throttle sequential mouse events to 1 every 20ms.\n",
1413 | " rubberband.mousemove('motion_notify', mouse_event_fn);\n",
1414 | "\n",
1415 | " rubberband.mouseenter('figure_enter', mouse_event_fn);\n",
1416 | " rubberband.mouseleave('figure_leave', mouse_event_fn);\n",
1417 | "\n",
1418 | " canvas_div.on(\"wheel\", function (event) {\n",
1419 | " event = event.originalEvent;\n",
1420 | " event['data'] = 'scroll'\n",
1421 | " if (event.deltaY < 0) {\n",
1422 | " event.step = 1;\n",
1423 | " } else {\n",
1424 | " event.step = -1;\n",
1425 | " }\n",
1426 | " mouse_event_fn(event);\n",
1427 | " });\n",
1428 | "\n",
1429 | " canvas_div.append(canvas);\n",
1430 | " canvas_div.append(rubberband);\n",
1431 | "\n",
1432 | " this.rubberband = rubberband;\n",
1433 | " this.rubberband_canvas = rubberband[0];\n",
1434 | " this.rubberband_context = rubberband[0].getContext(\"2d\");\n",
1435 | " this.rubberband_context.strokeStyle = \"#000000\";\n",
1436 | "\n",
1437 | " this._resize_canvas = function(width, height) {\n",
1438 | " // Keep the size of the canvas, canvas container, and rubber band\n",
1439 | " // canvas in synch.\n",
1440 | " canvas_div.css('width', width)\n",
1441 | " canvas_div.css('height', height)\n",
1442 | "\n",
1443 | " canvas.attr('width', width * mpl.ratio);\n",
1444 | " canvas.attr('height', height * mpl.ratio);\n",
1445 | " canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n",
1446 | "\n",
1447 | " rubberband.attr('width', width);\n",
1448 | " rubberband.attr('height', height);\n",
1449 | " }\n",
1450 | "\n",
1451 | " // Set the figure to an initial 600x600px, this will subsequently be updated\n",
1452 | " // upon first draw.\n",
1453 | " this._resize_canvas(600, 600);\n",
1454 | "\n",
1455 | " // Disable right mouse context menu.\n",
1456 | " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n",
1457 | " return false;\n",
1458 | " });\n",
1459 | "\n",
1460 | " function set_focus () {\n",
1461 | " canvas.focus();\n",
1462 | " canvas_div.focus();\n",
1463 | " }\n",
1464 | "\n",
1465 | " window.setTimeout(set_focus, 100);\n",
1466 | "}\n",
1467 | "\n",
1468 | "mpl.figure.prototype._init_toolbar = function() {\n",
1469 | " var fig = this;\n",
1470 | "\n",
1471 | " var nav_element = $('
');\n",
1472 | " nav_element.attr('style', 'width: 100%');\n",
1473 | " this.root.append(nav_element);\n",
1474 | "\n",
1475 | " // Define a callback function for later on.\n",
1476 | " function toolbar_event(event) {\n",
1477 | " return fig.toolbar_button_onclick(event['data']);\n",
1478 | " }\n",
1479 | " function toolbar_mouse_event(event) {\n",
1480 | " return fig.toolbar_button_onmouseover(event['data']);\n",
1481 | " }\n",
1482 | "\n",
1483 | " for(var toolbar_ind in mpl.toolbar_items) {\n",
1484 | " var name = mpl.toolbar_items[toolbar_ind][0];\n",
1485 | " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n",
1486 | " var image = mpl.toolbar_items[toolbar_ind][2];\n",
1487 | " var method_name = mpl.toolbar_items[toolbar_ind][3];\n",
1488 | "\n",
1489 | " if (!name) {\n",
1490 | " // put a spacer in here.\n",
1491 | " continue;\n",
1492 | " }\n",
1493 | " var button = $(' ');\n",
1494 | " button.addClass('ui-button ui-widget ui-state-default ui-corner-all ' +\n",
1495 | " 'ui-button-icon-only');\n",
1496 | " button.attr('role', 'button');\n",
1497 | " button.attr('aria-disabled', 'false');\n",
1498 | " button.click(method_name, toolbar_event);\n",
1499 | " button.mouseover(tooltip, toolbar_mouse_event);\n",
1500 | "\n",
1501 | " var icon_img = $(' ');\n",
1502 | " icon_img.addClass('ui-button-icon-primary ui-icon');\n",
1503 | " icon_img.addClass(image);\n",
1504 | " icon_img.addClass('ui-corner-all');\n",
1505 | "\n",
1506 | " var tooltip_span = $(' ');\n",
1507 | " tooltip_span.addClass('ui-button-text');\n",
1508 | " tooltip_span.html(tooltip);\n",
1509 | "\n",
1510 | " button.append(icon_img);\n",
1511 | " button.append(tooltip_span);\n",
1512 | "\n",
1513 | " nav_element.append(button);\n",
1514 | " }\n",
1515 | "\n",
1516 | " var fmt_picker_span = $(' ');\n",
1517 | "\n",
1518 | " var fmt_picker = $(' ');\n",
1519 | " fmt_picker.addClass('mpl-toolbar-option ui-widget ui-widget-content');\n",
1520 | " fmt_picker_span.append(fmt_picker);\n",
1521 | " nav_element.append(fmt_picker_span);\n",
1522 | " this.format_dropdown = fmt_picker[0];\n",
1523 | "\n",
1524 | " for (var ind in mpl.extensions) {\n",
1525 | " var fmt = mpl.extensions[ind];\n",
1526 | " var option = $(\n",
1527 | " ' ', {selected: fmt === mpl.default_extension}).html(fmt);\n",
1528 | " fmt_picker.append(option);\n",
1529 | " }\n",
1530 | "\n",
1531 | " // Add hover states to the ui-buttons\n",
1532 | " $( \".ui-button\" ).hover(\n",
1533 | " function() { $(this).addClass(\"ui-state-hover\");},\n",
1534 | " function() { $(this).removeClass(\"ui-state-hover\");}\n",
1535 | " );\n",
1536 | "\n",
1537 | " var status_bar = $('');\n",
1538 | " nav_element.append(status_bar);\n",
1539 | " this.message = status_bar[0];\n",
1540 | "}\n",
1541 | "\n",
1542 | "mpl.figure.prototype.request_resize = function(x_pixels, y_pixels) {\n",
1543 | " // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n",
1544 | " // which will in turn request a refresh of the image.\n",
1545 | " this.send_message('resize', {'width': x_pixels, 'height': y_pixels});\n",
1546 | "}\n",
1547 | "\n",
1548 | "mpl.figure.prototype.send_message = function(type, properties) {\n",
1549 | " properties['type'] = type;\n",
1550 | " properties['figure_id'] = this.id;\n",
1551 | " this.ws.send(JSON.stringify(properties));\n",
1552 | "}\n",
1553 | "\n",
1554 | "mpl.figure.prototype.send_draw_message = function() {\n",
1555 | " if (!this.waiting) {\n",
1556 | " this.waiting = true;\n",
1557 | " this.ws.send(JSON.stringify({type: \"draw\", figure_id: this.id}));\n",
1558 | " }\n",
1559 | "}\n",
1560 | "\n",
1561 | "\n",
1562 | "mpl.figure.prototype.handle_save = function(fig, msg) {\n",
1563 | " var format_dropdown = fig.format_dropdown;\n",
1564 | " var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n",
1565 | " fig.ondownload(fig, format);\n",
1566 | "}\n",
1567 | "\n",
1568 | "\n",
1569 | "mpl.figure.prototype.handle_resize = function(fig, msg) {\n",
1570 | " var size = msg['size'];\n",
1571 | " if (size[0] != fig.canvas.width || size[1] != fig.canvas.height) {\n",
1572 | " fig._resize_canvas(size[0], size[1]);\n",
1573 | " fig.send_message(\"refresh\", {});\n",
1574 | " };\n",
1575 | "}\n",
1576 | "\n",
1577 | "mpl.figure.prototype.handle_rubberband = function(fig, msg) {\n",
1578 | " var x0 = msg['x0'] / mpl.ratio;\n",
1579 | " var y0 = (fig.canvas.height - msg['y0']) / mpl.ratio;\n",
1580 | " var x1 = msg['x1'] / mpl.ratio;\n",
1581 | " var y1 = (fig.canvas.height - msg['y1']) / mpl.ratio;\n",
1582 | " x0 = Math.floor(x0) + 0.5;\n",
1583 | " y0 = Math.floor(y0) + 0.5;\n",
1584 | " x1 = Math.floor(x1) + 0.5;\n",
1585 | " y1 = Math.floor(y1) + 0.5;\n",
1586 | " var min_x = Math.min(x0, x1);\n",
1587 | " var min_y = Math.min(y0, y1);\n",
1588 | " var width = Math.abs(x1 - x0);\n",
1589 | " var height = Math.abs(y1 - y0);\n",
1590 | "\n",
1591 | " fig.rubberband_context.clearRect(\n",
1592 | " 0, 0, fig.canvas.width, fig.canvas.height);\n",
1593 | "\n",
1594 | " fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n",
1595 | "}\n",
1596 | "\n",
1597 | "mpl.figure.prototype.handle_figure_label = function(fig, msg) {\n",
1598 | " // Updates the figure title.\n",
1599 | " fig.header.textContent = msg['label'];\n",
1600 | "}\n",
1601 | "\n",
1602 | "mpl.figure.prototype.handle_cursor = function(fig, msg) {\n",
1603 | " var cursor = msg['cursor'];\n",
1604 | " switch(cursor)\n",
1605 | " {\n",
1606 | " case 0:\n",
1607 | " cursor = 'pointer';\n",
1608 | " break;\n",
1609 | " case 1:\n",
1610 | " cursor = 'default';\n",
1611 | " break;\n",
1612 | " case 2:\n",
1613 | " cursor = 'crosshair';\n",
1614 | " break;\n",
1615 | " case 3:\n",
1616 | " cursor = 'move';\n",
1617 | " break;\n",
1618 | " }\n",
1619 | " fig.rubberband_canvas.style.cursor = cursor;\n",
1620 | "}\n",
1621 | "\n",
1622 | "mpl.figure.prototype.handle_message = function(fig, msg) {\n",
1623 | " fig.message.textContent = msg['message'];\n",
1624 | "}\n",
1625 | "\n",
1626 | "mpl.figure.prototype.handle_draw = function(fig, msg) {\n",
1627 | " // Request the server to send over a new figure.\n",
1628 | " fig.send_draw_message();\n",
1629 | "}\n",
1630 | "\n",
1631 | "mpl.figure.prototype.handle_image_mode = function(fig, msg) {\n",
1632 | " fig.image_mode = msg['mode'];\n",
1633 | "}\n",
1634 | "\n",
1635 | "mpl.figure.prototype.updated_canvas_event = function() {\n",
1636 | " // Called whenever the canvas gets updated.\n",
1637 | " this.send_message(\"ack\", {});\n",
1638 | "}\n",
1639 | "\n",
1640 | "// A function to construct a web socket function for onmessage handling.\n",
1641 | "// Called in the figure constructor.\n",
1642 | "mpl.figure.prototype._make_on_message_function = function(fig) {\n",
1643 | " return function socket_on_message(evt) {\n",
1644 | " if (evt.data instanceof Blob) {\n",
1645 | " /* FIXME: We get \"Resource interpreted as Image but\n",
1646 | " * transferred with MIME type text/plain:\" errors on\n",
1647 | " * Chrome. But how to set the MIME type? It doesn't seem\n",
1648 | " * to be part of the websocket stream */\n",
1649 | " evt.data.type = \"image/png\";\n",
1650 | "\n",
1651 | " /* Free the memory for the previous frames */\n",
1652 | " if (fig.imageObj.src) {\n",
1653 | " (window.URL || window.webkitURL).revokeObjectURL(\n",
1654 | " fig.imageObj.src);\n",
1655 | " }\n",
1656 | "\n",
1657 | " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
1658 | " evt.data);\n",
1659 | " fig.updated_canvas_event();\n",
1660 | " fig.waiting = false;\n",
1661 | " return;\n",
1662 | " }\n",
1663 | " else if (typeof evt.data === 'string' && evt.data.slice(0, 21) == \"data:image/png;base64\") {\n",
1664 | " fig.imageObj.src = evt.data;\n",
1665 | " fig.updated_canvas_event();\n",
1666 | " fig.waiting = false;\n",
1667 | " return;\n",
1668 | " }\n",
1669 | "\n",
1670 | " var msg = JSON.parse(evt.data);\n",
1671 | " var msg_type = msg['type'];\n",
1672 | "\n",
1673 | " // Call the \"handle_{type}\" callback, which takes\n",
1674 | " // the figure and JSON message as its only arguments.\n",
1675 | " try {\n",
1676 | " var callback = fig[\"handle_\" + msg_type];\n",
1677 | " } catch (e) {\n",
1678 | " console.log(\"No handler for the '\" + msg_type + \"' message type: \", msg);\n",
1679 | " return;\n",
1680 | " }\n",
1681 | "\n",
1682 | " if (callback) {\n",
1683 | " try {\n",
1684 | " // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n",
1685 | " callback(fig, msg);\n",
1686 | " } catch (e) {\n",
1687 | " console.log(\"Exception inside the 'handler_\" + msg_type + \"' callback:\", e, e.stack, msg);\n",
1688 | " }\n",
1689 | " }\n",
1690 | " };\n",
1691 | "}\n",
1692 | "\n",
1693 | "// from http://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n",
1694 | "mpl.findpos = function(e) {\n",
1695 | " //this section is from http://www.quirksmode.org/js/events_properties.html\n",
1696 | " var targ;\n",
1697 | " if (!e)\n",
1698 | " e = window.event;\n",
1699 | " if (e.target)\n",
1700 | " targ = e.target;\n",
1701 | " else if (e.srcElement)\n",
1702 | " targ = e.srcElement;\n",
1703 | " if (targ.nodeType == 3) // defeat Safari bug\n",
1704 | " targ = targ.parentNode;\n",
1705 | "\n",
1706 | " // jQuery normalizes the pageX and pageY\n",
1707 | " // pageX,Y are the mouse positions relative to the document\n",
1708 | " // offset() returns the position of the element relative to the document\n",
1709 | " var x = e.pageX - $(targ).offset().left;\n",
1710 | " var y = e.pageY - $(targ).offset().top;\n",
1711 | "\n",
1712 | " return {\"x\": x, \"y\": y};\n",
1713 | "};\n",
1714 | "\n",
1715 | "/*\n",
1716 | " * return a copy of an object with only non-object keys\n",
1717 | " * we need this to avoid circular references\n",
1718 | " * http://stackoverflow.com/a/24161582/3208463\n",
1719 | " */\n",
1720 | "function simpleKeys (original) {\n",
1721 | " return Object.keys(original).reduce(function (obj, key) {\n",
1722 | " if (typeof original[key] !== 'object')\n",
1723 | " obj[key] = original[key]\n",
1724 | " return obj;\n",
1725 | " }, {});\n",
1726 | "}\n",
1727 | "\n",
1728 | "mpl.figure.prototype.mouse_event = function(event, name) {\n",
1729 | " var canvas_pos = mpl.findpos(event)\n",
1730 | "\n",
1731 | " if (name === 'button_press')\n",
1732 | " {\n",
1733 | " this.canvas.focus();\n",
1734 | " this.canvas_div.focus();\n",
1735 | " }\n",
1736 | "\n",
1737 | " var x = canvas_pos.x * mpl.ratio;\n",
1738 | " var y = canvas_pos.y * mpl.ratio;\n",
1739 | "\n",
1740 | " this.send_message(name, {x: x, y: y, button: event.button,\n",
1741 | " step: event.step,\n",
1742 | " guiEvent: simpleKeys(event)});\n",
1743 | "\n",
1744 | " /* This prevents the web browser from automatically changing to\n",
1745 | " * the text insertion cursor when the button is pressed. We want\n",
1746 | " * to control all of the cursor setting manually through the\n",
1747 | " * 'cursor' event from matplotlib */\n",
1748 | " event.preventDefault();\n",
1749 | " return false;\n",
1750 | "}\n",
1751 | "\n",
1752 | "mpl.figure.prototype._key_event_extra = function(event, name) {\n",
1753 | " // Handle any extra behaviour associated with a key event\n",
1754 | "}\n",
1755 | "\n",
1756 | "mpl.figure.prototype.key_event = function(event, name) {\n",
1757 | "\n",
1758 | " // Prevent repeat events\n",
1759 | " if (name == 'key_press')\n",
1760 | " {\n",
1761 | " if (event.which === this._key)\n",
1762 | " return;\n",
1763 | " else\n",
1764 | " this._key = event.which;\n",
1765 | " }\n",
1766 | " if (name == 'key_release')\n",
1767 | " this._key = null;\n",
1768 | "\n",
1769 | " var value = '';\n",
1770 | " if (event.ctrlKey && event.which != 17)\n",
1771 | " value += \"ctrl+\";\n",
1772 | " if (event.altKey && event.which != 18)\n",
1773 | " value += \"alt+\";\n",
1774 | " if (event.shiftKey && event.which != 16)\n",
1775 | " value += \"shift+\";\n",
1776 | "\n",
1777 | " value += 'k';\n",
1778 | " value += event.which.toString();\n",
1779 | "\n",
1780 | " this._key_event_extra(event, name);\n",
1781 | "\n",
1782 | " this.send_message(name, {key: value,\n",
1783 | " guiEvent: simpleKeys(event)});\n",
1784 | " return false;\n",
1785 | "}\n",
1786 | "\n",
1787 | "mpl.figure.prototype.toolbar_button_onclick = function(name) {\n",
1788 | " if (name == 'download') {\n",
1789 | " this.handle_save(this, null);\n",
1790 | " } else {\n",
1791 | " this.send_message(\"toolbar_button\", {name: name});\n",
1792 | " }\n",
1793 | "};\n",
1794 | "\n",
1795 | "mpl.figure.prototype.toolbar_button_onmouseover = function(tooltip) {\n",
1796 | " this.message.textContent = tooltip;\n",
1797 | "};\n",
1798 | "mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n",
1799 | "\n",
1800 | "mpl.extensions = [\"eps\", \"jpeg\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n",
1801 | "\n",
1802 | "mpl.default_extension = \"png\";var comm_websocket_adapter = function(comm) {\n",
1803 | " // Create a \"websocket\"-like object which calls the given IPython comm\n",
1804 | " // object with the appropriate methods. Currently this is a non binary\n",
1805 | " // socket, so there is still some room for performance tuning.\n",
1806 | " var ws = {};\n",
1807 | "\n",
1808 | " ws.close = function() {\n",
1809 | " comm.close()\n",
1810 | " };\n",
1811 | " ws.send = function(m) {\n",
1812 | " //console.log('sending', m);\n",
1813 | " comm.send(m);\n",
1814 | " };\n",
1815 | " // Register the callback with on_msg.\n",
1816 | " comm.on_msg(function(msg) {\n",
1817 | " //console.log('receiving', msg['content']['data'], msg);\n",
1818 | " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
1819 | " ws.onmessage(msg['content']['data'])\n",
1820 | " });\n",
1821 | " return ws;\n",
1822 | "}\n",
1823 | "\n",
1824 | "mpl.mpl_figure_comm = function(comm, msg) {\n",
1825 | " // This is the function which gets called when the mpl process\n",
1826 | " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
1827 | "\n",
1828 | " var id = msg.content.data.id;\n",
1829 | " // Get hold of the div created by the display call when the Comm\n",
1830 | " // socket was opened in Python.\n",
1831 | " var element = $(\"#\" + id);\n",
1832 | " var ws_proxy = comm_websocket_adapter(comm)\n",
1833 | "\n",
1834 | " function ondownload(figure, format) {\n",
1835 | " window.open(figure.imageObj.src);\n",
1836 | " }\n",
1837 | "\n",
1838 | " var fig = new mpl.figure(id, ws_proxy,\n",
1839 | " ondownload,\n",
1840 | " element.get(0));\n",
1841 | "\n",
1842 | " // Call onopen now - mpl needs it, as it is assuming we've passed it a real\n",
1843 | " // web socket which is closed, not our websocket->open comm proxy.\n",
1844 | " ws_proxy.onopen();\n",
1845 | "\n",
1846 | " fig.parent_element = element.get(0);\n",
1847 | " fig.cell_info = mpl.find_output_cell(\"
\");\n",
1848 | " if (!fig.cell_info) {\n",
1849 | " console.error(\"Failed to find cell for figure\", id, fig);\n",
1850 | " return;\n",
1851 | " }\n",
1852 | "\n",
1853 | " var output_index = fig.cell_info[2]\n",
1854 | " var cell = fig.cell_info[0];\n",
1855 | "\n",
1856 | "};\n",
1857 | "\n",
1858 | "mpl.figure.prototype.handle_close = function(fig, msg) {\n",
1859 | " var width = fig.canvas.width/mpl.ratio\n",
1860 | " fig.root.unbind('remove')\n",
1861 | "\n",
1862 | " // Update the output cell to use the data from the current canvas.\n",
1863 | " fig.push_to_output();\n",
1864 | " var dataURL = fig.canvas.toDataURL();\n",
1865 | " // Re-enable the keyboard manager in IPython - without this line, in FF,\n",
1866 | " // the notebook keyboard shortcuts fail.\n",
1867 | " IPython.keyboard_manager.enable()\n",
1868 | " $(fig.parent_element).html(' ');\n",
1869 | " fig.close_ws(fig, msg);\n",
1870 | "}\n",
1871 | "\n",
1872 | "mpl.figure.prototype.close_ws = function(fig, msg){\n",
1873 | " fig.send_message('closing', msg);\n",
1874 | " // fig.ws.close()\n",
1875 | "}\n",
1876 | "\n",
1877 | "mpl.figure.prototype.push_to_output = function(remove_interactive) {\n",
1878 | " // Turn the data on the canvas into data in the output cell.\n",
1879 | " var width = this.canvas.width/mpl.ratio\n",
1880 | " var dataURL = this.canvas.toDataURL();\n",
1881 | " this.cell_info[1]['text/html'] = ' ';\n",
1882 | "}\n",
1883 | "\n",
1884 | "mpl.figure.prototype.updated_canvas_event = function() {\n",
1885 | " // Tell IPython that the notebook contents must change.\n",
1886 | " IPython.notebook.set_dirty(true);\n",
1887 | " this.send_message(\"ack\", {});\n",
1888 | " var fig = this;\n",
1889 | " // Wait a second, then push the new image to the DOM so\n",
1890 | " // that it is saved nicely (might be nice to debounce this).\n",
1891 | " setTimeout(function () { fig.push_to_output() }, 1000);\n",
1892 | "}\n",
1893 | "\n",
1894 | "mpl.figure.prototype._init_toolbar = function() {\n",
1895 | " var fig = this;\n",
1896 | "\n",
1897 | " var nav_element = $('
');\n",
1898 | " nav_element.attr('style', 'width: 100%');\n",
1899 | " this.root.append(nav_element);\n",
1900 | "\n",
1901 | " // Define a callback function for later on.\n",
1902 | " function toolbar_event(event) {\n",
1903 | " return fig.toolbar_button_onclick(event['data']);\n",
1904 | " }\n",
1905 | " function toolbar_mouse_event(event) {\n",
1906 | " return fig.toolbar_button_onmouseover(event['data']);\n",
1907 | " }\n",
1908 | "\n",
1909 | " for(var toolbar_ind in mpl.toolbar_items){\n",
1910 | " var name = mpl.toolbar_items[toolbar_ind][0];\n",
1911 | " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n",
1912 | " var image = mpl.toolbar_items[toolbar_ind][2];\n",
1913 | " var method_name = mpl.toolbar_items[toolbar_ind][3];\n",
1914 | "\n",
1915 | " if (!name) { continue; };\n",
1916 | "\n",
1917 | " var button = $(' ');\n",
1918 | " button.click(method_name, toolbar_event);\n",
1919 | " button.mouseover(tooltip, toolbar_mouse_event);\n",
1920 | " nav_element.append(button);\n",
1921 | " }\n",
1922 | "\n",
1923 | " // Add the status bar.\n",
1924 | " var status_bar = $(' ');\n",
1925 | " nav_element.append(status_bar);\n",
1926 | " this.message = status_bar[0];\n",
1927 | "\n",
1928 | " // Add the close button to the window.\n",
1929 | " var buttongrp = $('
');\n",
1930 | " var button = $(' ');\n",
1931 | " button.click(function (evt) { fig.handle_close(fig, {}); } );\n",
1932 | " button.mouseover('Stop Interaction', toolbar_mouse_event);\n",
1933 | " buttongrp.append(button);\n",
1934 | " var titlebar = this.root.find($('.ui-dialog-titlebar'));\n",
1935 | " titlebar.prepend(buttongrp);\n",
1936 | "}\n",
1937 | "\n",
1938 | "mpl.figure.prototype._root_extra_style = function(el){\n",
1939 | " var fig = this\n",
1940 | " el.on(\"remove\", function(){\n",
1941 | "\tfig.close_ws(fig, {});\n",
1942 | " });\n",
1943 | "}\n",
1944 | "\n",
1945 | "mpl.figure.prototype._canvas_extra_style = function(el){\n",
1946 | " // this is important to make the div 'focusable\n",
1947 | " el.attr('tabindex', 0)\n",
1948 | " // reach out to IPython and tell the keyboard manager to turn it's self\n",
1949 | " // off when our div gets focus\n",
1950 | "\n",
1951 | " // location in version 3\n",
1952 | " if (IPython.notebook.keyboard_manager) {\n",
1953 | " IPython.notebook.keyboard_manager.register_events(el);\n",
1954 | " }\n",
1955 | " else {\n",
1956 | " // location in version 2\n",
1957 | " IPython.keyboard_manager.register_events(el);\n",
1958 | " }\n",
1959 | "\n",
1960 | "}\n",
1961 | "\n",
1962 | "mpl.figure.prototype._key_event_extra = function(event, name) {\n",
1963 | " var manager = IPython.notebook.keyboard_manager;\n",
1964 | " if (!manager)\n",
1965 | " manager = IPython.keyboard_manager;\n",
1966 | "\n",
1967 | " // Check for shift+enter\n",
1968 | " if (event.shiftKey && event.which == 13) {\n",
1969 | " this.canvas_div.blur();\n",
1970 | " event.shiftKey = false;\n",
1971 | " // Send a \"J\" for go to next cell\n",
1972 | " event.which = 74;\n",
1973 | " event.keyCode = 74;\n",
1974 | " manager.command_mode();\n",
1975 | " manager.handle_keydown(event);\n",
1976 | " }\n",
1977 | "}\n",
1978 | "\n",
1979 | "mpl.figure.prototype.handle_save = function(fig, msg) {\n",
1980 | " fig.ondownload(fig, null);\n",
1981 | "}\n",
1982 | "\n",
1983 | "\n",
1984 | "mpl.find_output_cell = function(html_output) {\n",
1985 | " // Return the cell and output element which can be found *uniquely* in the notebook.\n",
1986 | " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n",
1987 | " // IPython event is triggered only after the cells have been serialised, which for\n",
1988 | " // our purposes (turning an active figure into a static one), is too late.\n",
1989 | " var cells = IPython.notebook.get_cells();\n",
1990 | " var ncells = cells.length;\n",
1991 | " for (var i=0; i= 3 moved mimebundle to data attribute of output\n",
1998 | " data = data.data;\n",
1999 | " }\n",
2000 | " if (data['text/html'] == html_output) {\n",
2001 | " return [cell, data, j];\n",
2002 | " }\n",
2003 | " }\n",
2004 | " }\n",
2005 | " }\n",
2006 | "}\n",
2007 | "\n",
2008 | "// Register the function which deals with the matplotlib target/channel.\n",
2009 | "// The kernel may be null if the page has been refreshed.\n",
2010 | "if (IPython.notebook.kernel != null) {\n",
2011 | " IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n",
2012 | "}\n"
2013 | ],
2014 | "text/plain": [
2015 | ""
2016 | ]
2017 | },
2018 | "metadata": {},
2019 | "output_type": "display_data"
2020 | },
2021 | {
2022 | "data": {
2023 | "text/html": [
2024 | " "
2025 | ],
2026 | "text/plain": [
2027 | ""
2028 | ]
2029 | },
2030 | "metadata": {},
2031 | "output_type": "display_data"
2032 | }
2033 | ],
2034 | "source": [
2035 | "%matplotlib notebook\n",
2036 | "arg = c_l[category]\n",
2037 | "print('Class number: ', arg)\n",
2038 | "y1 = extract_membership(y_test_new, arg)\n",
2039 | "y1_th = thresholding(y1, threshold)\n",
2040 | "y1_std = linear_stretch(y1_th)\n",
2041 | "\n",
2042 | "strg = category\n",
2043 | "name = 'soft'+ strg\n",
2044 | "\n",
2045 | "display_save_image(y1_std, row, col, name)"
2046 | ]
2047 | },
2048 | {
2049 | "cell_type": "code",
2050 | "execution_count": null,
2051 | "metadata": {},
2052 | "outputs": [],
2053 | "source": []
2054 | }
2055 | ],
2056 | "metadata": {
2057 | "kernelspec": {
2058 | "display_name": "Python 3",
2059 | "language": "python",
2060 | "name": "python3"
2061 | },
2062 | "language_info": {
2063 | "codemirror_mode": {
2064 | "name": "ipython",
2065 | "version": 3
2066 | },
2067 | "file_extension": ".py",
2068 | "mimetype": "text/x-python",
2069 | "name": "python",
2070 | "nbconvert_exporter": "python",
2071 | "pygments_lexer": "ipython3",
2072 | "version": "3.7.1"
2073 | }
2074 | },
2075 | "nbformat": 4,
2076 | "nbformat_minor": 2
2077 | }
2078 |
--------------------------------------------------------------------------------