Автоматизированная система колоризации полутонового изображения
Дипломная работа - Компьютеры, программирование
Другие дипломы по предмету Компьютеры, программирование
ментированного изображения пользователь выбирает обученную нейросеть для каждого участка, с помощью которой будет производиться колоризация выбранного участка изображения. В случае необходимости откорректировать полученные области сегментирования нужно нажать кнопку Выполнить сегментацию вручную:
Рисунок А.5 - Выполнение сегментации вручную
В случае выбора в пункте меню главного окна пункта Нейронная сеть появится окно редактирования параметров нейронных сетей:
Рисунок А.6 - Окно работы с нейронными сетями
В появившемся окне отображается список всех сетей, полученных в приложении. Каждую сеть можно удалить и отредактировать. Также отсюда производится создание новых сетей. Для обучения выбранной сети нужно нажать кнопку Обучить. Обучение сетей производится так же пользователем:
Рисунок А.7 - Обучение нейросети
Пользователь выбирает алгоритм обучения для сети (параметры которой, число нейронов в скрытом слое и функция активации, задал при ее создании), задает параметры обучения сети согласно выбранному алгоритму, выбирает изображения, на которых собирается обучить сеть и производит ее обучение. В ходе обучения пользователю предоставляется график ошибки обучения:
Рисунок А.8 - График ошибки обучения
Приложение 2. Листинг основных классов программы
В качестве алгоритма сегментации изображения был реализован алгоритм Efficient Graph-Based Image Segmentation авторов PedroF. Felzenszwalb (MIT) и DanielP. Huttenlocher (Cornell University). Для повышения производительности работы приложения было решено хранить изображение в форме одномерного вектора:
public class Image {w;h;[] data;cache;Image(BufferedImage image) {= image.getWidth();= image.getHeight();= new int[w * h]; // allocate space for image data(int i = 0; i < w * h; i++)[i] = image.getRGB(i % w, i / w);
}Image(int width, int height) {= width;= height;= new int[w * h]; // allocate space for image data
}(int i, int j) {data[j * w + i];
}void setIJ(int i, int j, intval) {[j * w + i] = val;
}
//caching buffered image for more high speed workvoid resetCache() {= null;
}() {(null == cache) {= new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);(int i = 0; i < w; i++) {(int j = 0; j < h; j++) {.setRGB(i, j, getIJ(i, j));
}
}
};
}
}
В качестве универсальной структуры работы с графами, позволяющей быстро соединять несколько графов и пересчитывать минимальные веса для решения задачи Штейнера, была выбрана структура Disjoint-setdatastructure:
public class DisjointSet {;[] elts;(int elements) {= new UniElt[elements];(int ii = 0; ii <elts.length; ii++)[ii] = new UniElt();= elements;(int i = 0; i < elements; i++) {[i].rank = 0;[i].p = i;[i].size = 1;
}
}find(int x) {y = x;(y != elts[y].p)= elts[y].p;[y].p = y;y;
}void join(int x, int y) {(elts[x].rank >elts[y].rank) {[y].p = x;[x].size += elts[y].size;
} else {[x].p = y;[y].size += elts[x].size;(elts[x].rank == elts[y].rank)
elts[y].rank++;
}
num--;
}
}
Для реализации понятия множество в алгоритме Краскала применяется структура данных Disjoint-setdatastructure. Работа с ней оптимизирована на выполнение двух основных операций: узнать для некоторой вершины, какому множеству в текущий момент она принадлежит; быстро объединить эти множества в одно.
Обучение сети производится в классах наследниках класса LearningRule:
public abstract class LearningRule extends Observable implements Runnable,{static final long serialVersionUID = 1L;NeuralNetwork neuralNetwork;transient TrainingSet trainingSet;transient volatile boolean stopLearning = false;LearningRule() {
}void setTrainingSet(TrainingSet trainingSet) {.trainingSet = trainingSet;
}TrainingSet getTrainingSet() {trainingSet;
}NeuralNetwork getNeuralNetwork() {neuralNetwork;
}void setNeuralNetwork(NeuralNetwork neuralNetwork) {.neuralNetwork = neuralNetwork;
}void run() {.learn(this.trainingSet);
}public void setStarted() {.stopLearning = false;
}public void stopLearning() {.stopLearning = true;
}public boolean isStopped() {this.stopLearning;
}void notifyChange() {();();();
}abstract void learn(TrainingSet trainingSet);
}
Каждый новый класс обучения наследуется от предыдущего, переопределяя его методы:
public class BackPropagation extends SigmoidDeltaRule {static final long serialVersionUID = 1L;BackPropagation() {();
}
@Overridevoid updateNetworkWeights(double[] patternError) {.adjustOutputNeurons(patternError);.adjustHiddenLayers();
0;i--){layer=neuralNetwork.getLayerAt(i);(Neuronneuron:layer.getNeurons()){delta=this.calculateDelta(neuron);.setError(delta);.updateNeuronWeights(neuron);">}void adjustHiddenLayers() {layerNum = this.neuralNetwork.getLayersCount();(int i = layerNum - 2; i > 0; i--) {layer = neuralNetwork.getLayerAt(i);(Neuron neuron : layer.getNeurons()) {delta = this.calculateDelta(neuron);.setError(delta);.updateNeuronWeights(neuron);
} // for
} // for
connectedTo=((Neuron)neuron).getOutConnections();delta_sum=0d;(Connectionconnection:connectedTo){d=connection.getToNeuron().getError()">}double calculateDelta(Neuron neuron) { connectedTo = ((Neuron) neuron).getOutConnections();delta_sum = 0d;(Connection connection : connectedTo) {d = connection.getToNeuron().getError()
* connection.getWeight().getValue();_sum += d; // weighted sum from the next layer
} // fortransferFunction = neuron.getTransferFunction();netInput = neuron.getNetInput();f1 = transferFunction.getDerivative(netInput);delta = f1 * delta_sum;
return delta;
}
}
Базовый класс функций активации:
public abstract class TransferFunction implements Serializable {static final long serialVersionUID = 1L;public double getOutput(double net);double getDerivative(double net) {1d;
}
@OverrideString toString() {getClass().getName();
}
}
Тангенсальная функция активации:class Tanh extends TransferFunction implements Serializable {static final long serialVersionUID = 2L;double slope = 2d;Tanh() {
}Tanh(double slope) {.slope = slope;
}Tanh(Properties properties) {{.slope = (Double) properties.getProperty("transferFunction.slope");
} catch (NullPointerException e) {new RuntimeException("properties are not set just leave default values");
} catch (NumberFormatException e) {new RuntimeException("Invalid transfer function properties! Using default values.");
}
}
@Overridepublic double getOutput(double net) {
// conditional logic helps to avoid NaN(net > 100) {1.0;
} else if (net < -100) {-1.0;
}E_x = Math.exp(this.slope * net);(E_x - 1d) / (E_x + 1d);
}
@Overridepublic double getDerivative(double net) {out = getOutput(net);(1d - out * out);
}double getSlope() {this.slope;
}void setSlope(double slope) {.slope = slope;
}
}
Класс нейросети:class NeuralNetwork extends Observable implements Runnable, Serializable {static final long serialVersionUID = 4L;NeuralNetworkType type;List();.addPlugin(new LabelsPlugin());
}void addLayer(Layer layer) {.setParent