Размытие Rect на скриншоте

Я разрабатываю приложение для Android, которое использует фон Service для программного захвата снимка экрана того, что в данный момент находится на экране. Я получаю скриншот как Bitmap.

Затем я успешно импортировал OpenCV в мой проект Android.

Теперь мне нужно размыть подмножество этого изображения, т. е. не все изображение целиком, а [прямоугольную] область или часть изображения. У меня есть массив объектов Rect, представляющих прямоугольные области, которые мне нужно размыть внутри скриншот.

Я искал учебник по работе с OpenCV в Java и не нашел четкого ответа. Mat и Imgproc, очевидно, представляют интерес, и есть Mat.submat() метод, но я не смог найти четкое и простое руководство по тому, как это сделать.

Я много гуглил, и ни один из примеров, которые я нашел, не является полным. Мне нужно сделать это на Java в среде выполнения Android.

Мне нужно: Bitmap >>> Mat >>> Imgproc>>> Rect >>> Bitmap с размытым ROI.

Любые опытные разработчики OpenCV здесь, можете ли вы указать мне правильное направление? Это единственное, на чем я застрял.

Связанные:

Размытие по Гауссу с OpenCV: размытие только части изображения?.

Как размыть прямоугольник с помощью OpenCv.

Как размыть часть изображения в Android?.


person Y.S    schedule 29.01.2020    source источник
comment
Проще говоря, вы можете извлечь область интереса в отдельный мат, применить фильтрацию к этому мату и повторно вставить его в исходное изображение. Или я что-то здесь упускаю?   -  person Andreas    schedule 30.01.2020
comment
Я думаю, что я что-то упустил, потому что вопрос кажется мне таким простым! В c++, если img — это ваш Mat, а r — ваш Rect, то img(r) будет самим изображением, и вы можете независимо передать его функции размытия =› blur(img(r), img(r), ksize);   -  person MH304    schedule 02.02.2020


Ответы (2)


Код C++ для решения этой задачи представлен ниже с комментариями и примерами изображений:

// load an input image
Mat img = imread("C:\\elon_tusk.png");

изображение:

введите описание изображения здесь

// extract subimage
Rect roi(113, 87, 100, 50);
Mat subimg = img(roi);

субкартинка:

введите описание изображения здесь

// blur the subimage
Mat blurred_subimage;
GaussianBlur(subimg, blurred_subimage, Size(0, 0), 5, 5);

blurred_subimage:

введите описание изображения здесь

// copy the blurred subimage back to the original image
blurred_subimage.copyTo(img(roi));

изображение:

введите описание изображения здесь

Эквивалент Android:

Mat img = Imgcodecs.imread("elon_tusk.png");
Rect roi = new Rect(113, 87, 100, 50);
Mat subimage = img.submat(roi).clone();
Imgproc.GaussianBlur(subimg, subimg, new Size(0,0), 5, 5);
subimg.copyTo(img.submat(roi));
person karlphillip    schedule 02.02.2020
comment
это то же самое, что я написал, но я все равно проголосовал за более подробный ответ! - person kalzso; 03.02.2020
comment
Обновленный ответ с кодом Android. Не знаю, работает ли это, не смог проверить. Посмотрите на этот файл, чтобы узнать, как импортировать материалы из OpenCV. - person karlphillip; 03.02.2020
comment
Идеальный выбор входного изображения - person nathancy; 04.02.2020
comment
@karlphillip: спасибо, что не поленились. Ваш код, скорее всего, является правильным ответом. Отчитаюсь после того, как опробую... ;) - person Y.S; 05.02.2020
comment
Я не думаю, что вам нужно делать копию обратно. насколько я помню, Mat subimage = img.submat(roi) должен создать указатель на область исходного изображения. и если вы размоете субизображение, вы автоматически размоете оригинал (ЕСЛИ ВЫ НЕ КЛОНИРУЕТЕ ЕГО). - person hagor; 07.02.2020
comment
karlphillip Я работал с вашим кодом, который я считаю правильным, но я не смог дойти до логического конца. Не могли бы вы помочь мне с этим вопросом, который является продолжением нашего обсуждения здесь? @hagor, не могли бы вы также взглянуть, пожалуйста? Я добавлю награду за то же самое, как только SO позволит мне. Просим вашей помощи с тем же, и спасибо за ваше время ... :) - person Y.S; 21.02.2020
comment
@ Y.S, что вы подразумеваете под логическим концом? - person hagor; 27.02.2020

Вы можете просто реализовать свою собственную вспомогательную функцию, назовем ее roi (область интереса). Поскольку изображения в opencv представляют собой пустые ndarrays, вы можете сделать что-то вроде этого:

def roi(image: np.ndarray, region: QRect) -> np.ndarray:
    a1 = region.upperLeft().x()
    b1 = region.bottomRight().y()
    a2 = region.upperLeft().x()
    b2 = region.bottomRight().y()
    return image[a1:a2, b1:b2]

И просто используйте эту вспомогательную функцию, чтобы извлечь интересующие вас части изображения, размыть их и вернуть результат на исходное изображение.

person kalzso    schedule 01.02.2020