SOL4Py Sample: AugmentedImagePreview
|
#******************************************************************************
#
# Copyright (c) 2018-2019 Antillia.com TOSHIYUKI ARAI. ALL RIGHTS RESERVED.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#******************************************************************************
# AugmentedImagePreview.py
# 2019/04/16
# encodig: utf-8
import sys
import os
import traceback
import errno
sys.path.append('../')
from SOL4Py.ZApplicationView import *
from SOL4Py.ZImageView import *
from SOL4Py.ZPushButton import *
from SOL4Py.ZScaleComboBox import *
from SOL4Py.ZHorizontalLayouter import *
from SOL4Py.ZVerticalPane import *
from SOL4Py.ZLabeledCheckBox import *
from SOL4Py.ZLabeledDoubleSpinBox import *
from SOL4Py.opencv.ZOpenCVCroppedImageReader import *
from keras.preprocessing.image import ImageDataGenerator
class MainView(ZApplicationView):
IMAGE_COUNT = 25
IMAGE_COUNT_PERLINE= 5
# MainView Constructor
def __init__(self, title, x, y, width, height):
super(MainView, self).__init__(title, x, y, width, height, Z.Vertical)
self.get_layout().setSpacing(0)
self.scale = 50
self.get_layout().setContentsMargins(0,0,0,0);
self.scale_combobox = ZScaleComboBox(None, "Scale")
self.scale_combobox.current_scale(self.scale)
self.add(self.scale_combobox)
self.image_views = [None] * self.IMAGE_COUNT #
filename = "../images/Car_101.png"
# 1. Create our default ImageDataGenerator with rotation_range
self.generator = self.create_generator()
# 2 Create an inner widget.
self.inner = QWidget(self.main_layouter)
# 3 Set QSizePolicy.Expanding to the self.inner
self.inner.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
# 4 Create a grid layout for the inner widget.
self.grid = QGridLayout(self.inner)
# 5 Add an instance of ZImageView to the grid.
try:
self.size = (224, 224)
# Get an image cropped with max square region and scaled with self.size
image = self.load_cropped_scaled_image(filename, self.size)
# (height, width, channles) to (1, height, width, channels)
self.data = image.reshape((1,) + image.shape)
# 6 Get flow from the self.generator
flow = self.generator.flow(self.data, batch_size=1)
# 7 Get generated images from the flow.
for i in range(self.IMAGE_COUNT):
# 8 Create an instance of ZImageView
self.image_views[i] = ZImageView(self, 0, 0, 300, 300)
# 9 Get a generated image from the flow.
batches = next(flow)
generated = batches[0].astype(np.uint8)
self.image_views[i].set_image(generated)
self.image_views[i].rescale(self.scale)
x = int(i % self.IMAGE_COUNT_PERLINE)
y = int(i / self.IMAGE_COUNT_PERLINE)
self.grid.addWidget(self.image_views[i], y, x)
self.set_filenamed_title(filename)
except:
traceback.print_exc()
# 10 Add the inner to the self.
self.add(self.inner)
# 11 Add scale_changed callback to the self.scale_combobox.
self.scale_combobox.add_activate_callback(self.scale_changed)
self.show()
def create_generator(self):
# Create an instance ImageDataGenerator from self.*_range's
return ImageDataGenerator(
rotation_range = self.rotation_range.get_value(),
width_shift_range = self.width_shift_range.get_value(),
height_shift_range = self.height_shift_range.get_value(),
shear_range = self.shear_range.get_value(),
zoom_range = self.zoom_range.get_value(),
brightness_range = [self.brightness_low_range.get_value(),
self.brightness_high_range.get_value()],
channel_shift_range= self.channel_shift_range.get_value(),
horizontal_flip = self.horizontal_flip.is_checked(),
vertical_flip = self.vertical_flip.is_checked())
def add_control_pane(self, fixed_width=200):
self.vpane = ZVerticalPane(self, fixed_width)
# Create preview PushButton
self.preview = ZPushButton("Preview", self.vpane)
self.preview.add_activated_callback(self.do_preview)
self.vpane.add(self.preview)
self.spacing = QLabel(" ")
self.vpane.add(self.spacing)
self.label = QLabel("ImageDataGenerator Parameters:")
self.vpane.add(self.label)
#self.groupBox.setLayout(self.vpane.get_layout())
self.rotation_range = ZLabeledDoubleSpinBox(self.vpane, "rotation_range",
0, 30, 20, step=1.0)
self.width_shift_range = ZLabeledDoubleSpinBox(self.vpane, "width_shift_range",
0, 2.0, 1.0, step=0.1)
self.height_shift_range = ZLabeledDoubleSpinBox(self.vpane, "height_shift_range",
0, 2.0, 0.3, step=0.1)
self.shear_range = ZLabeledDoubleSpinBox(self.vpane, "shear_range",
0, 2.0, 0.4, step=0.1)
self.zoom_range = ZLabeledDoubleSpinBox(self.vpane, "zoom_range",
0, 2.0, 0.3, step=0.1)
self.channel_shift_range = ZLabeledDoubleSpinBox(self.vpane, "channel_shift",
0, 3.0, 2.0, step=0.1)
self.brightness_low_range = ZLabeledDoubleSpinBox(self.vpane, "brightness_low_range",
0.5, 1.0, 0.7, step=0.1)
self.brightness_high_range = ZLabeledDoubleSpinBox(self.vpane, "brightness_high_range",
1.0, 1.5, 1.2, step=0.1)
self.horizontal_flip = ZLabeledCheckBox(self.vpane, "horizontal_flip")
self.vertical_flip = ZLabeledCheckBox(self.vpane, "vertical_flip")
self.vpane.add(self.rotation_range)
self.vpane.add(self.width_shift_range)
self.vpane.add(self.height_shift_range)
self.vpane.add(self.shear_range)
self.vpane.add(self.zoom_range)
self.vpane.add(self.channel_shift_range)
self.vpane.add(self.brightness_low_range)
self.vpane.add(self.brightness_high_range)
self.vpane.add(self.horizontal_flip)
self.vpane.add(self.vertical_flip)
self.set_right_dock(self.vpane)
# Callback to the preview PushButton
def do_preview(self):
self.inner.hide()
try:
# 1. Create a new instance of ImageDataGenerator.
self.generator = self.create_generator()
# 2 Get a flow from the self.generator
flow = self.generator.flow(self.data, batch_size=1)
# 3 Get generated images from the flow.
for i in range(self.IMAGE_COUNT):
batches = next(flow)
generated = batches[0].astype(np.uint8)
self.image_views[i].set_image(generated)
self.image_views[i].rescale(self.scale)
except:
traceback.print_exc()
self.grid.update()
self.inner.show()
def load_file(self, filename):
self.inner.hide()
# Get an image cropped with max square region and scaled with scale
image = self.load_cropped_scaled_image(filename, self.size)
# (height, width, channles) to (1, height, width, channels)
data = image.reshape((1,) + image.shape)
flow = self.generator.flow(data, batch_size=1)
for i in range(self.IMAGE_COUNT):
batches = next(flow)
generated = batches[0].astype(np.uint8)
self.image_views[i].set_image(generated)
self.image_views[i].rescale(self.scale)
self.grid.update()
self.inner.show()
def load_cropped_scaled_image(self, filename, size):
reader = ZOpenCVCroppedImageReader()
image = reader.read(filename)
return reader.crop_max_square_region(image, size)
# Scale changed callback
def scale_changed(self, text):
text = text.replace("%", "")
scale = int(text) # percentage
# Hide self.inner to avoid the flickering of image_views
self.inner.hide()
for i in range(self.IMAGE_COUNT):
self.image_views[i].rescale(scale)
# You should call update method of self.grid layout
self.grid.update()
self.inner.show()
def file_open(self):
options = QFileDialog.Options()
filename, _ = QFileDialog.getOpenFileName(self,"FileOpenDialog", "",
"All Files (*);;Image Files (*.png;*jpg;*.jpeg)", options=options)
if filename:
self.load_file(filename)
self.set_filenamed_title(filename)
def file_save(self):
# 1 Show a folderDialog to select a folder to save generated images
folder = QFileDialog.getExistingDirectory(self,
"OpenFolder",
os.path.expanduser('.'),
QFileDialog.ShowDirsOnly)
if folder:
#dir = dir.replace('/', os.sep)
print("Folder button clicked {}".format(folder))
self.inner.hide()
try:
# 1. Create a new instance of ImageDataGenerator.
self.generator = self.create_generator()
# 2 Get a flow from the self.generator
flow = self.generator.flow(self.data, batch_size=1,
save_to_dir = folder,
save_prefix = "gen",
save_format= "png")
# 3 Get generated images from the flow.
for i in range(self.IMAGE_COUNT):
batches = next(flow)
generated = batches[0].astype(np.uint8)
self.image_views[i].set_image(generated)
self.image_views[i].rescale(self.scale)
except:
traceback.print_exc()
self.grid.update()
self.inner.show()
#*************************************************
#
if main(__name__):
try:
app_name = os.path.basename(sys.argv[0])
applet = QApplication(sys.argv)
main_view = MainView(app_name, 40, 40, 800, 640)
main_view.show ()
applet.exec_()
except:
traceback.print_exc()
Last modified:13 May 2019