opencv как визуализировать непрямоугольную область (roi)

У меня есть изображение (cv :: Mat) и ROI, который можно рассматривать как маску. Я хочу показать оригинальное изображение с ROI, смешанным над ним.

Моя маска меньше моего исходного изображения: каждый элемент представляет собой блок на изображении. Предположим, что моя маска это (обратите внимание, что моя маска НЕ ​​прямоугольник)

0  0  1
1  1  1
0  0  0

тогда я бы хотел, чтобы части, в которых (mask == 1), не трогали, а остальные смешивали с цветом. Это код у меня

cv::Mat blocks = image.clone;
uint npixcol = 32;
uint npixrow = 32;
for (uint ri = 0; ri < 480; ++ri)
for (uint ci = 0; ci < 640; ++ci)
{
if (mask[ri * 640 + ci])
cv::rectangle(blocks, cv::Rect(ci * npixcol, ri * npixrow, npixcol, npixrow), cv::Scalar(0, 0, 0), CV_FILLED, 8, 0);
}
cv::addWeighted(image, 0.5, blocks, 0.5, 0, image, -1);

Как я могу сделать это без дополнительной команды «клон», поскольку это не очень производительный …

чтобы сделать это более ясным; это пример того, что я хочу (цвет на самом деле не имеет значения)!введите описание изображения здесь

2

Решение

Ваша маска имеет постоянный цвет? Предполагая, что маска имеет тот же размер, что и изображение (вы можете легко масштабировать его):

//Manually instead of addWeighted()
for (uint ri = 0; ri < 480; ++ri)
for (uint ci = 0; ci < 640; ++ci)
{
if (mask[ri * 640 + ci])
{
image.at<uchar>(ri,ci) [0] = image.at<uchar>(ri,ci) [0] * weight_blue;
image.at<uchar>(ri,ci) [1] = image.at<uchar>(ri,ci) [1] * weight_green;
image.at<uchar>(ri,ci) [2] = image.at<uchar>(ri,ci) [2] * weight_red;
}

}
2

Другие решения

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

#include <cstdlib>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>int
main(int argc, char *argv[])
{
cv::Mat image = cv::imread(argv[1]);
cv::Mat mask = cv::Mat::zeros(image.size(), CV_8U);
// let's put some 1 in my test mask.
cv::Mat roi = mask(cv::Rect(0,0,mask.cols/2, mask.rows/2));
roi = 1;

cv::Vec3b blue(255,0,0); // (B,G,R)
float alpha = 0.5;
// Let's have fun with iterators
cv::MatConstIterator_<unsigned char> maskIter = mask.begin<unsigned char>();
const cv::MatConstIterator_<unsigned char> maskIterEnd = mask.end<unsigned char>();
cv::MatIterator_<cv::Vec3b> imageIter = image.begin<cv::Vec3b>();
for (; maskIter != maskIterEnd; ++maskIter, ++imageIter) {
if (*maskIter) {// mask == 1
*imageIter = (1-alpha)*(*imageIter) + alpha*blue; // same as addWeighted
}
}

cv::namedWindow("image", 0);
cv::imshow("image", image);
cv::waitKey(0);
return EXIT_SUCCESS;
}
1

По сути, вы хотите проверить, если вы находитесь в Рой. Затем он должен вернуть указатель на исходное изображение. Если вы не внутри, вы хотите иметь какой-то цвет.

Вы можете сделать это с помощью своей собственной обертки для Мата.

MyMat::at(int x, int y){
if(inRoi(x,y)){
return original.at(x,y);
else
return color(0,0,0);
}

Я не думаю, что вы можете указать подизображение изображения на другое изображение. (Это означает, что я не думаю, что вы можете перенаправить пиксель вашего синего изображения на исходное изображение)

Mat blueImage;
Rect roi;
Mat roiInImage = blueImage(roi);
roiInImage.redirect = originalImage(roi); //don't think something like this is possible
0
По вопросам рекламы [email protected]