diff --git a/DataUtils/LaddGenerator/Program.cs b/DataUtils/LaddGenerator/Program.cs index 23beb56..3a5b9a4 100644 --- a/DataUtils/LaddGenerator/Program.cs +++ b/DataUtils/LaddGenerator/Program.cs @@ -73,7 +73,7 @@ static void Main(string[] args) if (dstAnnotation.Objects == null || dstAnnotation.Objects.Count <= 0) { dstAnnotation.Objects = new List(); - //throw new Exception("no objects in the image!"); + throw new Exception("no objects in the image!"); } foreach (var obj in dstAnnotation.Objects) { diff --git a/RescuerLaApp/Models/Docker.cs b/RescuerLaApp/Models/Docker.cs index fccd91a..a79c7e6 100755 --- a/RescuerLaApp/Models/Docker.cs +++ b/RescuerLaApp/Models/Docker.cs @@ -281,7 +281,7 @@ public async Task Remove(string imageName = "gosha20777/test", string tag = "1") } } - var images = await _client.Images.ListImagesAsync(new ImagesListParameters(){MatchName = imageName}); + var images = await _client.Images.ListImagesAsync(new ImagesListParameters(){MatchName = $"{imageName}:{tag}"}); foreach (var image in images) { await _client.Images.DeleteImageAsync(image.ID, new ImageDeleteParameters {Force = true}); diff --git a/RescuerLaApp/Models/TextTableBuilder.cs b/RescuerLaApp/Models/TextTableBuilder.cs new file mode 100644 index 0000000..12410e5 --- /dev/null +++ b/RescuerLaApp/Models/TextTableBuilder.cs @@ -0,0 +1,118 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace RescuerLaApp.Models +{ + public interface ITextRow + { + String Output(); + void Output(StringBuilder sb); + Object Tag { get; set; } + } + + public class TextTableBuilder : IEnumerable + { + protected class TextRow : List, ITextRow + { + protected TextTableBuilder owner = null; + public TextRow(TextTableBuilder Owner) + { + owner = Owner; + if (owner == null) throw new ArgumentException("Owner"); + } + public String Output() + { + StringBuilder sb = new StringBuilder(); + Output(sb); + return sb.ToString(); + } + public void Output(StringBuilder sb) + { + sb.AppendFormat(owner.FormatString, this.ToArray()); + } + public Object Tag { get; set; } + } + + public String Separator { get; set; } + + protected List rows = new List(); + protected List colLength = new List(); + + public TextTableBuilder() + { + Separator = " "; + } + + public TextTableBuilder(String separator) + : this() + { + Separator = separator; + } + + public ITextRow AddRow(params object[] cols) + { + TextRow row = new TextRow(this); + foreach (object o in cols) + { + String str = o.ToString().Trim(); + row.Add(str); + if (colLength.Count >= row.Count) + { + int curLength = colLength[row.Count - 1]; + if (str.Length > curLength) colLength[row.Count - 1] = str.Length; + } + else + { + colLength.Add(str.Length); + } + } + rows.Add(row); + return row; + } + + protected String _fmtString = null; + public String FormatString + { + get + { + if (_fmtString == null) + { + String format = ""; + int i = 0; + foreach (int len in colLength) + { + format += String.Format("{{{0},-{1}}}{2}", i++, len, Separator); + } + format += "\r\n"; + _fmtString = format; + } + return _fmtString; + } + } + + public String Output() + { + StringBuilder sb = new StringBuilder(); + foreach (TextRow row in rows) + { + row.Output(sb); + } + return sb.ToString(); + } + + #region IEnumerable Members + + public IEnumerator GetEnumerator() + { + return rows.GetEnumerator(); + } + + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() + { + return rows.GetEnumerator(); + } + + #endregion + } +} \ No newline at end of file diff --git a/RescuerLaApp/Program.cs b/RescuerLaApp/Program.cs index 8558f83..9ae8e23 100755 --- a/RescuerLaApp/Program.cs +++ b/RescuerLaApp/Program.cs @@ -11,7 +11,7 @@ internal static class Program { private static void Main(string[] args) { - Console.WriteLine("Lacmus desktop application. Version 0.2.9 alpha. \nCopyright (c) 2019 Georgy Perevozghikov \nGithub page: https://github.com/lizaalert/lacmus/.\nProvided by Yandex Cloud: https://cloud.yandex.com/."); + Console.WriteLine("Lacmus desktop application. Version 0.3.0 alpha. \nCopyright (c) 2019 Georgy Perevozghikov \nGithub page: https://github.com/lizaalert/lacmus/.\nProvided by Yandex Cloud: https://cloud.yandex.com/."); Console.WriteLine("This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'."); Console.WriteLine("This is free software, and you are welcome to redistribute it\nunder certain conditions; type `show c' for details."); Console.WriteLine("------------------------------------"); diff --git a/RescuerLaApp/RescuerLaApp.csproj b/RescuerLaApp/RescuerLaApp.csproj index 2b72727..fca7e35 100755 --- a/RescuerLaApp/RescuerLaApp.csproj +++ b/RescuerLaApp/RescuerLaApp.csproj @@ -21,6 +21,8 @@ + + diff --git a/RescuerLaApp/ViewModels/MainWindowViewModel.cs b/RescuerLaApp/ViewModels/MainWindowViewModel.cs index 0e63040..4c7e306 100755 --- a/RescuerLaApp/ViewModels/MainWindowViewModel.cs +++ b/RescuerLaApp/ViewModels/MainWindowViewModel.cs @@ -6,12 +6,21 @@ using System.Linq; using System.Reactive; using System.Reactive.Linq; +using System.Runtime.InteropServices; +using System.Text; using System.Threading.Tasks; +using Avalonia; using Avalonia.Controls; using Avalonia.Media.Imaging; +using Docker.DotNet; +using MessageBox.Avalonia.DTO; +using MessageBox.Avalonia.Enums; +using MessageBox.Avalonia.Models; +using MetadataExtractor; using ReactiveUI; using ReactiveUI.Fody.Helpers; using Newtonsoft.Json; +using Directory = System.IO.Directory; namespace RescuerLaApp.ViewModels { @@ -61,6 +70,12 @@ public MainWindowViewModel() UpdateModelCommand = ReactiveCommand.Create(UpdateModel, canExecute); ShowPerestriansCommand = ReactiveCommand.Create(ShowPedestrians, canExecute); ImportAllCommand = ReactiveCommand.Create(ImportAll, canExecute); + SaveAllImagesWithObjectsCommand = ReactiveCommand.Create(SaveAllImagesWithObjects, canExecute); + ShowAllMetadataCommand = ReactiveCommand.Create(ShowAllMetadata, canExecute); + ShowGeoDataCommand = ReactiveCommand.Create(ShowGeoData, canExecute); + HelpCommand = ReactiveCommand.Create(Help); + AboutCommand = ReactiveCommand.Create(About); + ExitCommand = ReactiveCommand.Create(Exit, canExecute); } public void UpdateFramesRepo() @@ -118,6 +133,16 @@ public void UpdateFramesRepo() public ReactiveCommand UpdateModelCommand { get; } public ReactiveCommand ShowPerestriansCommand { get; } + + public ReactiveCommand SaveAllImagesWithObjectsCommand { get; } + + public ReactiveCommand ShowAllMetadataCommand { get; } + public ReactiveCommand ShowGeoDataCommand { get; } + public ReactiveCommand HelpCommand { get; } + public ReactiveCommand AboutCommand { get; } + public ReactiveCommand ExitCommand { get; } + + #endregion @@ -368,6 +393,49 @@ private async void SaveAll() }; } } + + private async void SaveAllImagesWithObjects() + { + try + { + if (Frames == null || Frames.Count < 1) + { + Status = new AppStatusInfo() {Status = Enums.Status.Ready}; + return; + } + Status = new AppStatusInfo() {Status = Enums.Status.Working}; + + var openDig = new OpenFolderDialog() + { + Title = "Choose a directory to save images with objects" + }; + var dirName = await openDig.ShowAsync(new Window()); + + + if (string.IsNullOrEmpty(dirName) || !Directory.Exists(dirName)) + { + Status = new AppStatusInfo() {Status = Enums.Status.Ready}; + return; + } + + foreach (var frame in Frames) + { + if (frame.Rectangles == null || frame.Rectangles.Count <= 0) + continue; + File.Copy(frame.Patch, Path.Combine(dirName, Path.GetFileName(frame.Patch))); + } + Console.WriteLine($"Saved to {dirName}"); + Status = new AppStatusInfo() {Status = Enums.Status.Ready, StringStatus = $"Success | saved to {dirName}"}; + } + catch (Exception ex) + { + Status = new AppStatusInfo() + { + Status = Enums.Status.Error, + StringStatus = $"Error | {ex.Message.Replace('\n', ' ')}" + }; + } + } private async void ImportAll() { @@ -478,6 +546,140 @@ private void FrameLoadingProgressUpdate() } } + public void Help() + { + OpenUrl("https://github.com/lizaalert/lacmus/wiki"); + } + + public void ShowGeoData() + { + string msg = string.Empty; + int rows = 0; + var directories = ImageMetadataReader.ReadMetadata(Frames[SelectedIndex].Patch); + foreach (var directory in directories) + foreach (var tag in directory.Tags) + { + if (directory.Name.ToLower() == "gps") + { + if (tag.Name.ToLower() == "gps latitude" || + tag.Name.ToLower() == "gps longitude" || + tag.Name.ToLower() == "gps altitude") + { + rows++; + msg += $"{tag.Name}: {tag.Description}\n"; + } + } + } + + if (rows != 3) + msg = "This image have hot geo tags.\nUse `Show all metadata` more for more details."; + var msgbox = new MessageBox.Avalonia.MessageBoxWindow(new MessageBoxParams + { + Button = ButtonEnum.Ok, + ContentTitle = $"Geo position of {Path.GetFileName(Frames[SelectedIndex].Patch)}", + ContentMessage = msg, + Icon = Icon.Info, + Style = Style.None, + ShowInCenter = true + }); + msgbox.Show(); + } + + public void ShowAllMetadata() + { + var tb = new TextTableBuilder(); + tb.AddRow("Group", "Tag name", "Description"); + tb.AddRow("-----", "--------", "-----------"); + + + var directories = ImageMetadataReader.ReadMetadata(Frames[SelectedIndex].Patch); + foreach (var directory in directories) + foreach (var tag in directory.Tags) + tb.AddRow(directory.Name, tag.Name, tag.Description); + + var msgbox = new MessageBox.Avalonia.MessageBoxWindow(new MessageBoxParams + { + Button = ButtonEnum.Ok, + ContentTitle = $"Metadata of {Path.GetFileName(Frames[SelectedIndex].Patch)}", + ContentMessage = tb.Output(), + Icon = Icon.Info, + Style = Style.None, + ShowInCenter = true + }); + msgbox.Show(); + } + + public async void About() + { + var message = + "Copyright (c) 2019 Georgy Perevozghikov \nGithub page: https://github.com/lizaalert/lacmus/. Press `Github` button for more details.\nProvided by Yandex Cloud: https://cloud.yandex.com/." + + "\nThis program comes with ABSOLUTELY NO WARRANTY." + + "\nThis is free software, and you are welcome to redistribute it under GNU GPLv3 conditions.\nPress `License` button to learn more about the license"; + + var msgBoxCustomParams = new MessageBoxCustomParams + { + ButtonDefinitions = new [] + { + new ButtonDefinition{Name = "Ok", Type = ButtonType.Colored}, + new ButtonDefinition{Name = "License"}, + new ButtonDefinition{Name = "Github"} + }, + ContentTitle = "About", + ContentHeader = "Lacmus desktop application. Version 0.3.0 alpha.", + ContentMessage = message, + Icon = Icon.Avalonia, + Style = Style.None, + ShowInCenter = true + }; + var msgbox = MessageBox.Avalonia.MessageBoxWindow.CreateCustomWindow(msgBoxCustomParams); + var result = await msgbox.Show(); + switch (result.ToLower()) + { + case "ok": return; + case "license": OpenUrl("https://github.com/lizaalert/lacmus/blob/master/LICENSE"); break; + case "github": OpenUrl("https://github.com/lizaalert/lacmus"); break; + } + } + + public async void Exit() + { + var message = "Do you really want to exit?"; + + var msgbox = new MessageBox.Avalonia.MessageBoxWindow(new MessageBoxParams + { + Button = ButtonEnum.YesNo, + ContentTitle = "Exit", + ContentMessage = message, + Icon = Icon.Info, + Style = Style.None, + ShowInCenter = true + }); + var result = await msgbox.Show(); + if(result.ToLower() == "yes") + Application.Current.MainWindow.Close(); + } + + private void OpenUrl(string url) + { + try + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + System.Diagnostics.Process.Start(url); + } + else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || + RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + { + System.Diagnostics.Process.Start("x-www-browser", url); + } + } + catch (Exception e) + { + Console.WriteLine(e); + } + + } + private void UpdateUi() { /*TODO: Вынести сюда все функции обновления UI*/ diff --git a/RescuerLaApp/Views/MainWindow.xaml b/RescuerLaApp/Views/MainWindow.xaml index ea6d584..193bd5c 100755 --- a/RescuerLaApp/Views/MainWindow.xaml +++ b/RescuerLaApp/Views/MainWindow.xaml @@ -23,8 +23,9 @@ + - + @@ -41,9 +42,9 @@ - + - + @@ -112,8 +113,15 @@ VerticalAlignment="Stretch" Background="{Binding ImageBrush}" Height="{Binding CanvasHeight, Mode=TwoWay}" - Width="{Binding CanvasWidth, Mode=TwoWay}" - /> + Width="{Binding CanvasWidth, Mode=TwoWay}"> + + + + + + + + diff --git a/RetinaNet/config.ini b/RetinaNet/config.ini index c04192a..bdb1be0 100644 --- a/RetinaNet/config.ini +++ b/RetinaNet/config.ini @@ -1,5 +1,5 @@ [anchor_parameters] -sizes = 16 32 64 128 +sizes = 16 32 64 128 256 strides = 8 16 32 64 128 ratios = 0.5 1 2 3 scales = 1 1.2 1.6