public static Bitmap CaptureFromDisplay(ref ImageCaptureInfo info) { Bitmap b = new Bitmap((int)info.actual_crop_size_x, (int)info.actual_crop_size_y); //Full screen var watch = System.Diagnostics.Stopwatch.StartNew(); using (Graphics g = Graphics.FromImage(b)) { g.CopyFromScreen((int)(info.center_of_frame_x - info.actual_crop_size_x / 2 + info.actual_offset_x), (int)(info.center_of_frame_y - info.actual_crop_size_y / 2 + info.actual_offset_y), 0, 0, new Size((int)info.actual_crop_size_x, (int)info.actual_crop_size_y), CopyPixelOperation.SourceCopy); } if (b.Size.Width != info.featureSizeX && b.Size.Height != info.featureSizeY) { ResizeNearestNeighbor filter = new ResizeNearestNeighbor(info.featureSizeX, info.featureSizeY); b = filter.Apply(b); } watch.Stop(); var elapsedMs = watch.ElapsedMilliseconds; return(b); }
public static Bitmap PrintWindow(IntPtr hwnd, ref ImageCaptureInfo info, bool full = false, bool useCrop = false, float scalingValueFloat = 1.0f) { try { var watch = System.Diagnostics.Stopwatch.StartNew(); Rectangle rc; DLLImportStuff.GetClientRect(hwnd, out rc); Bitmap ret = new Bitmap(1, 1); if (rc.Width < 0) { return(ret); } IntPtr hdcwnd = DLLImportStuff.GetDC(hwnd); IntPtr hdc = DLLImportStuff.CreateCompatibleDC(hdcwnd); rc.Width = (int)(rc.Width * scalingValueFloat); rc.Height = (int)(rc.Height * scalingValueFloat); if (useCrop) { //Change size according to selected crop rc.Width = (int)(info.crop_coordinate_right - info.crop_coordinate_left); rc.Height = (int)(info.crop_coordinate_bottom - info.crop_coordinate_top); } //Compute crop coordinates and width/ height based on resolution ImageCapture.SizeAdjustedCropAndOffset(rc.Width, rc.Height, ref info); float cropOffsetX = info.actual_offset_x; float cropOffsetY = info.actual_offset_y; if (full) { info.actual_offset_x = 0; info.actual_offset_y = 0; info.actual_crop_size_x = 2 * info.center_of_frame_x; info.actual_crop_size_y = 2 * info.center_of_frame_y; } if (useCrop) { //Adjust for crop offset info.center_of_frame_x += info.crop_coordinate_left; info.center_of_frame_y += info.crop_coordinate_top; } IntPtr hbmp = DLLImportStuff.CreateCompatibleBitmap(hdcwnd, (int)info.actual_crop_size_x, (int)info.actual_crop_size_y); DLLImportStuff.SelectObject(hdc, hbmp); DLLImportStuff.BitBlt(hdc, 0, 0, (int)info.actual_crop_size_x, (int)info.actual_crop_size_y, hdcwnd, (int)(info.center_of_frame_x + info.actual_offset_x - info.actual_crop_size_x / 2), (int)(info.center_of_frame_y + info.actual_offset_y - info.actual_crop_size_y / 2), DLLImportStuff.TernaryRasterOperations.SRCCOPY); info.actual_offset_x = cropOffsetX; info.actual_offset_y = cropOffsetY; ret = (Bitmap)Image.FromHbitmap(hbmp).Clone(); DLLImportStuff.DeleteObject(hbmp); DLLImportStuff.ReleaseDC(hwnd, hdcwnd); DLLImportStuff.DeleteDC(hdc); if (ret.Size.Width != info.featureSizeX && ret.Size.Height != info.featureSizeY) { ResizeNearestNeighbor filter = new ResizeNearestNeighbor(info.featureSizeX, info.featureSizeY); ret = filter.Apply(ret); } watch.Stop(); var elapsedMs = watch.ElapsedMilliseconds; return(ret); } catch (System.Runtime.InteropServices.ExternalException ex) { return(new Bitmap(10, 10)); } }
//Should probably refactor this into some kind of struct, whatever... public static void SizeAdjustedCropAndOffset(int device_width, int device_height, ref ImageCaptureInfo info) { var resolution_factor_x = (device_width / info.captureResolutionX); var resolution_factor_y = (device_height / info.captureResolutionY); info.actual_crop_size_x = info.featureSizeX * resolution_factor_x; info.actual_crop_size_y = info.featureSizeY * resolution_factor_y; //Scale offset depending on resolution info.actual_offset_x = info.cropOffsetX * resolution_factor_x; info.actual_offset_y = info.cropOffsetY * resolution_factor_y; //Scale offset and sizes depending on actual vs. needed aspect ratio if (((float)device_width / (float)device_height) > (info.captureAspectRatio)) { var image_region = (float)device_height / (1.0f / info.captureAspectRatio); //Aspect ratio is larger than original var black_bar_width_total = (float)device_width - image_region; //Compute space occupied by black border relative to total width var adjust_factor = ((float)(device_width - black_bar_width_total) / (float)device_width); info.actual_crop_size_x *= adjust_factor; info.actual_offset_x *= adjust_factor; } else { var image_region = (float)device_width / (info.captureAspectRatio); //Aspect ratio is larger than original var black_bar_height_total = (float)device_height - image_region; //Compute space occupied by black border relative to total width var adjust_factor = ((float)(device_height - black_bar_height_total) / (float)device_height); info.actual_crop_size_y *= adjust_factor; info.actual_offset_y *= adjust_factor; } info.center_of_frame_x = device_width / 2; info.center_of_frame_y = device_height / 2; }
/// <summary> /// Opens 2 folders (loading / non-loading examples), and automatically trains and tunes the hyperparameters of the SVM detection. /// </summary> public static DetectorParameters OptimizeDetectorFromFolders(ImageCaptureInfo info, string settingsPath) { // TODO: determine if accord+svm is fast enough for real-time detection // TODO: implement "record" tab in livesplit plugin to record data, which can then be used/sorted for training. // TODO: cleanup. load both datasets. fill them with more data (especially the regular gameplay case), then find best model with largest separation // we can easily do this be passing the number of bins, and patch sizes via grid search, compute features, etc. // the optimization criterion is largest difference between min and max log likelihood. we then simply choose the middle one. // these settings will then be stored in a JSON file so it's optimized per game. DetectorParameters best_detector_params = new DetectorParameters(); DetectorParameters current_detector_params = new DetectorParameters(); FolderBrowserDialog fbd = new FolderBrowserDialog(); fbd.RootFolder = System.Environment.SpecialFolder.MyComputer; fbd.SelectedPath = settingsPath; fbd.Description = "Choose a folder containing image patches captured during LOADING."; if (fbd.ShowDialog() != DialogResult.OK) { return(null); } string positive_path = fbd.SelectedPath; fbd = new FolderBrowserDialog(); fbd.RootFolder = System.Environment.SpecialFolder.MyComputer; fbd.SelectedPath = settingsPath; fbd.Description = "Choose a folder containing image patches captured during regular gameplay."; if (fbd.ShowDialog() != DialogResult.OK) { return(null); } string negative_path = fbd.SelectedPath; // Setup grid search parameters int[] patch_sizes_x = { info.featureSizeX, info.featureSizeX / 2, info.featureSizeX / 4, info.featureSizeX / 8 }; //{ 10, 20, 25, 50, 100, 300 }; int[] patch_sizes_y = { info.featureSizeY, info.featureSizeY / 2, info.featureSizeY / 4, info.featureSizeY / 8 }; //{ 10, 20, 25, 50, 100 }; int[] number_of_histogram_bins = { 4, 8, 16 }; foreach (var patch_size_x in patch_sizes_x) { foreach (var patch_size_y in patch_sizes_y) { foreach (var histogram_bins in number_of_histogram_bins) { System.Console.WriteLine("Training: pX = " + patch_size_x + ", pY = " + patch_size_y + ", bins = " + histogram_bins); current_detector_params = new DetectorParameters(); current_detector_params.HistogramPatchSizeX = patch_size_x; current_detector_params.HistogramPatchSizeY = patch_size_y; current_detector_params.HistogramNumberOfBins = histogram_bins; var positive_data = FeaturesFromFolder(positive_path, current_detector_params); var negative_data = FeaturesFromFolder(negative_path, current_detector_params); current_detector_params = PerformTraining(positive_data, negative_data, current_detector_params); if (current_detector_params.DetectsPerfectly && current_detector_params.LogLikelihoodDistance > best_detector_params.LogLikelihoodDistance) { best_detector_params = (DetectorParameters)current_detector_params.Clone(); } } } } System.Console.WriteLine("Best parameters: "); System.Console.WriteLine("HistogramPatchSizeX: " + best_detector_params.HistogramPatchSizeX); System.Console.WriteLine("HistogramPatchSizeY: " + best_detector_params.HistogramPatchSizeY); System.Console.WriteLine("HistogramNumberOfBins: " + best_detector_params.HistogramNumberOfBins); System.Console.WriteLine("MinLogLikelihoodPositive: " + best_detector_params.MinLogLikelihoodPositive); System.Console.WriteLine("MaxLogLikelihoodNegative: " + best_detector_params.MaxLogLikelihoodNegative); System.Console.WriteLine("LogLikelihoodDistance: " + best_detector_params.LogLikelihoodDistance); System.Console.WriteLine("LogLikelihoodThreshold: " + best_detector_params.LogLikelihoodThreshold); return(best_detector_params); }