Вырезка кусков изображений

Здравствуйте. Есть у меня изображение которое содержит много разных кусочков.
Типа такого

image

По аналогии с текстурами. В общем мне нужен софт или сервис как можно на автомате найти все эти куски и вырезать их каждый в свое отдельное изображение.

Вроде помню для юнити как то делал так, но сейчас в упор не могу вспомнить чем и как.
Фотошоп тоже как выяснилось не умеет такое.

хз про сервис, но гугл выдал как сделать на Питоне с OpenCV в пару строк: opencv - How extract pictures from an big image in python - Stack Overflow

Правда сделать фон прозрачным оказалось не так просто. В итоге сработало как тут: numpy - Python OpenCV: Crop image to contents, and make background transparent - Stack Overflow

import cv2
import numpy as np

img = cv2.imread('image.png', cv2.IMREAD_UNCHANGED)

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
gray = 255 - gray # invert

thresh = cv2.threshold(gray,0,255,cv2.THRESH_BINARY)[1]

kernel = np.ones((3,3), np.uint8)
mask = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)
mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel)

new_img = cv2.cvtColor(img, cv2.COLOR_BGR2BGRA)
new_img[:, :, 3] = mask

contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

i = 0
for cnt in contours:
    i += 1
    (x,y,w,h) = cv2.boundingRect(cnt)
    crop = new_img[y:y+h, x:x+w]
    cv2.imwrite('res{}.png'.format(i), crop)

images.zip (4.6 КБ)

ну я код выродил вот такой:

/// подпрограмма вырезки фрагментов из изображения 

            OpenCvSharp.Cv2.NamedWindow("debug", OpenCvSharp.WindowFlags.FreeRatio | OpenCvSharp.WindowFlags.GuiNormal);

            using (OpenCvSharp.Mat imgorig = new OpenCvSharp.Mat(@"C:\Users\bobrov_ma\Pictures\img004.png", OpenCvSharp.ImreadModes.Unchanged))
            using (OpenCvSharp.Mat img = new OpenCvSharp.Mat(@"C:\Users\bobrov_ma\Pictures\img004.png", OpenCvSharp.ImreadModes.Grayscale))
            using (OpenCvSharp.Mat imgtmp = img.Clone())
            {
                OpenCvSharp.Cv2.BitwiseNot(img, img);
                OpenCvSharp.Cv2.Dilate(img, img, null, null, 3);
                int thres = 50;
                while (true)
                {
                    OpenCvSharp.Cv2.Threshold(img, imgtmp, thres, 255, OpenCvSharp.ThresholdTypes.Binary);
                    OpenCvSharp.Cv2.Dilate(imgtmp, imgtmp, null, null, 15);
                    OpenCvSharp.Cv2.Erode(imgtmp, imgtmp, null, null, 8);
                    //OpenCvSharp.Cv2.GaussianBlur(imgtmp, imgtmp, new OpenCvSharp.Size(3, 3), 0.3, 0.3);
                    OpenCvSharp.Cv2.Canny(imgtmp, imgtmp, 50, 255);


                    OpenCvSharp.Point[][] contrours = imgtmp.FindContoursAsArray(OpenCvSharp.RetrievalModes.External, OpenCvSharp.ContourApproximationModes.ApproxSimple);
                    OpenCvSharp.Point[] ActualCircle = null;
                    int max = int.MinValue;
                    OpenCvSharp.RotatedRect actualRect = new OpenCvSharp.RotatedRect();
                    int cnt = 0;
                    foreach (OpenCvSharp.Point[] cont in contrours)
                    {
                        if (cont.Length > 12)
                        {
                            OpenCvSharp.RotatedRect rct = OpenCvSharp.Cv2.MinAreaRect(cont);

                            imgorig[rct.BoundingRect()].SaveImage(@"C:\Delme\subsribes\" + (cnt++).ToString() + ".png");
                        }
                    }
                    //imgtmp.SaveImage("C:\\out.bmp");
                    OpenCvSharp.Cv2.ImShow("debug", imgtmp);
                    OpenCvSharp.Cv2.WaitKey(20);
                }
            }

Предварительно фон вырезал в фотошопе.

Причем так забавно … Ощутил на миг все могущество опыта … вспомнил как застал зарю OpenCV … версию 2,2 … даже пробовал поучавствовать в развитии … какой то метод оптимизировал и публиковал.
Сейчас через GIT обновил … это теперь прям система.
Чтобы реализовать код ушло буквально 30 минут … Понял уже после публикации вопроса. ))