61 setWindowTitle(
"Deep Dream Settings");
62 setMinimumSize(560, 620);
67 model_file_edit->setPlaceholderText(
"Select a TorchScript .pt model...");
75 layer_combo_box->addItems({
"relu1_1",
"relu1_2",
"relu2_1",
"relu2_2",
"relu3_1",
"relu3_2",
"relu3_3",
"relu4_1",
"relu4_2",
"relu4_3",
"relu5_1",
"relu5_2",
"relu5_3"});
102 fp16_check_box->setToolTip(
"Use half-precision model and working tensors to reduce CUDA memory "
103 "and improve performance.");
107 channel_spin_box->setToolTip(
"Enter a channel number, A, or All to select every channel.");
124 "zoom, or rotation. Fully applies on the next launch.");
126 auto *model_group =
new QGroupBox(
"Model",
this);
127 auto *model_layout =
new QFormLayout(model_group);
128 auto *model_row =
new QHBoxLayout;
131 model_layout->addRow(
"TorchScript model:", model_row);
135 auto *dream_group =
new QGroupBox(
"Gradient Ascent",
this);
136 auto *dream_layout =
new QFormLayout(dream_group);
145 auto *feedback_group =
new QGroupBox(
"Temporal Feedback",
this);
146 auto *feedback_layout =
new QFormLayout(feedback_group);
151 auto *performance_group =
new QGroupBox(
"Performance and Pipeline",
this);
152 auto *performance_layout =
new QFormLayout(performance_group);
158 auto *contents =
new QWidget(
this);
159 auto *contents_layout =
new QVBoxLayout(contents);
162 contents_layout->addWidget(model_group);
163 contents_layout->addWidget(dream_group);
164 contents_layout->addWidget(feedback_group);
165 contents_layout->addWidget(performance_group);
166 contents_layout->addStretch();
168 auto *scroll_area =
new QScrollArea(
this);
169 scroll_area->setWidgetResizable(
true);
170 scroll_area->setWidget(contents);
172 auto *buttons =
new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Apply | QDialogButtonBox::Cancel,
this);
173 QPushButton *randomize_button = buttons->addButton(
"Randomize", QDialogButtonBox::ActionRole);
174 randomize_button->setToolTip(
"Generate and immediately apply a random Deep Dream preset.");
175 auto *layout =
new QVBoxLayout(
this);
176 layout->addWidget(scroll_area, 1);
177 layout->addWidget(buttons);
186 connect(buttons, &QDialogButtonBox::rejected,
this, &QDialog::reject);
233 if (model_filename.isEmpty()) {
238 const QString metadata_filename = model_filename +
".json";
239 QFile metadata_file(metadata_filename);
240 const QFileInfo metadata_info(metadata_file);
242 if (!metadata_info.isFile()) {
246 constexpr qint64 MAXIMUM_METADATA_BYTES = 1024 * 1024;
247 if (metadata_info.size() <= 0 || metadata_info.size() > MAXIMUM_METADATA_BYTES) {
248 error =
"The model metadata sidecar has an invalid size.";
249 }
else if (!metadata_file.open(QIODevice::ReadOnly)) {
250 error =
"The model metadata sidecar could not be opened.";
253 QJsonDocument document;
254 if (error.isEmpty()) {
255 QJsonParseError parse_error;
256 document = QJsonDocument::fromJson(metadata_file.readAll(), &parse_error);
257 if (parse_error.error != QJsonParseError::NoError || !document.isObject()) {
258 error =
"The model metadata sidecar is not valid JSON.";
262 QString architecture;
263 QString default_layer;
265 int minimum_size = 0;
266 if (error.isEmpty()) {
267 const QJsonObject root = document.object();
268 if (root.value(
"format").toString() !=
"acmxvk-deep-dream" || root.value(
"version").toInt(-1) != 1) {
269 error =
"The sidecar is not supported ACMXVK Deep Dream metadata.";
271 architecture = root.value(
"architecture").toString().trimmed();
272 default_layer = root.value(
"default_layer").toString().trimmed();
273 const QJsonArray layer_array = root.value(
"layers").toArray();
274 static const QRegularExpression name_pattern(QStringLiteral(
"^[A-Za-z0-9_.-]{1,64}$"));
275 if (!name_pattern.match(architecture).hasMatch() || layer_array.isEmpty() || layer_array.size() > 256) {
276 error =
"The model metadata fields are invalid.";
278 for (
const QJsonValue value : layer_array) {
279 const QString name = value.toObject().value(
"name").toString().trimmed();
280 if (!name_pattern.match(name).hasMatch() || layers.contains(name)) {
281 error =
"The model metadata contains an invalid or duplicate layer.";
287 const QJsonObject input = root.value(
"input").toObject();
288 minimum_size = input.value(
"minimum_size").toInt(0);
289 if (error.isEmpty() && (!layers.contains(default_layer) || minimum_size < 1 || minimum_size > 4096)) {
290 error =
"The model default layer or input size is invalid.";
295 if (!error.isEmpty()) {
299 QMessageBox::warning(
this,
"Invalid Deep Dream Metadata", error +
"\n\n" + metadata_filename);
304 const QString selected_layer =
layer_combo_box->currentText().trimmed();
307 layer_combo_box->setCurrentText(layers.contains(selected_layer) ? selected_layer : default_layer);
308 model_metadata_label->setText(QString(
"%1, %2 feature layers, minimum input %3 px").arg(architecture).arg(layers.size()).arg(minimum_size));
353 QMessageBox::warning(
this,
"Deep Dream Model Required",
"Select a TorchScript model before randomizing.");
358 QRandomGenerator *random = QRandomGenerator::global();
371 zoom_spin_box->setValue(0.985 + random->generateDouble() * 0.03);
372 const double rotation_magnitude = 0.5 + random->generateDouble() * 2.5;
373 rotation_spin_box->setValue(random->bounded(2) == 0 ? -rotation_magnitude : rotation_magnitude);
374 static constexpr std::array<int, 4> RANDOM_DIMENSIONS = {256, 384, 512, 640};
376 maximum_dimension_spin_box->setValue(RANDOM_DIMENSIONS[
static_cast<std::size_t
>(random->bounded(
static_cast<int>(RANDOM_DIMENSIONS.size())))]);
400 QSettings settings(
"LostSideDead",
"acmx2");
401 enable_check_box->setChecked(settings.value(
"deep_dream/enabled",
false).toBool());
402 model_file_edit->setText(settings.value(
"deep_dream/model_file", QString()).toString());
403 layer_combo_box->setCurrentText(settings.value(
"deep_dream/layer",
"relu4_2").toString());
405 strength_spin_box->setValue(settings.value(
"deep_dream/strength", 0.05).toDouble());
406 feedback_spin_box->setValue(settings.value(
"deep_dream/feedback", 0.9).toDouble());
407 zoom_spin_box->setValue(settings.value(
"deep_dream/zoom", 1.01).toDouble());
408 rotation_spin_box->setValue(settings.value(
"deep_dream/rotation", 0.1).toDouble());
409 const int maximum_dimension = settings.value(
"deep_dream/maximum_dimension", 512).toInt();
412 fp16_check_box->setChecked(settings.value(
"deep_dream/fp16",
false).toBool());
413 channel_spin_box->setValue(settings.value(
"deep_dream/channel", -1).toInt());
414 octaves_spin_box->setValue(settings.value(
"deep_dream/octaves", 1).toInt());
416 jitter_spin_box->setValue(settings.value(
"deep_dream/jitter", 0).toInt());