RotatedRect ROI в OpenCV

У меня есть RotatedRect, я хочу немного обработать изображение в повернутой области (скажем, извлечь цветовую гистограмму). Как я могу получить рентабельность инвестиций? Я имею в виду получить область (пиксели), чтобы я мог выполнять обработку.

Я нашел это, но он меняет регион, используя < a href="http://opencv.willowgarage.com/documentation/cpp/geometric_image_transformations.html?highlight=rotationmatrix#getRotationMatrix2D" rel="nofollow noreferrer">getRotationMatrix2D и warpAffine, поэтому в моей ситуации это не работает (мне нужно обработать исходное изображение пикселей).
Затем я обнаружил, что это предлагает использовать маску, что звучит разумно, но может ли кто-нибудь научить меня, как получить маску в виде зеленого RotatedRect ниже.
  Зеленый RotatedRect — это область интереса, которую я хочу обработать

Кроме маски, есть ли другие решения?
Спасибо за подсказку


person vancexu    schedule 26.10.2012    source источник
comment
помогает это? Вам просто нужно использовать fillPoly, чтобы нарисовать повернутый прямоугольник. Вы можете получить 4 точки, ограничивающие его, используя его размер и угол.   -  person Hammer    schedule 26.10.2012


Ответы (4)


Вот мое решение с использованием маски:
Идея состоит в том, чтобы построить Mat mask, назначив 255 моему RotatedRect ROI.

Как узнать, какая точка находится в области интереса (которая должна быть назначена 255)?
Я использую следующую функцию isInROI для решения проблемы.

/** decide whether point p is in the ROI.
*** The ROI is a rotated rectange whose 4 corners are stored in roi[] 
**/
bool isInROI(Point p, Point2f roi[])
{
    double pro[4];
    for(int i=0; i<4; ++i)
    {
        pro[i] = computeProduct(p, roi[i], roi[(i+1)%4]);
    }
    if(pro[0]*pro[2]<0 && pro[1]*pro[3]<0)
    {
        return true;
    }
    return false;
}

/** function pro = kx-y+j, take two points a and b,
*** compute the line argument k and j, then return the pro value
*** so that can be used to determine whether the point p is on the left or right
*** of the line ab
**/
double computeProduct(Point p, Point2f a, Point2f b)
{
    double k = (a.y-b.y) / (a.x-b.x);
    double j = a.y - k*a.x;
    return k*p.x - p.y + j;
}

Как создать маску?
Используя следующий код.

Mat mask = Mat(image.size(), CV_8U, Scalar(0));
for(int i=0; i<image.rows; ++i)
{
    for(int j=0; j<image.cols; ++j)
    {
        Point p = Point(j,i);   // pay attention to the cordination
        if(isInROI(p,vertices))
        {
            mask.at<uchar>(i,j) = 255;
        }
    }
}

Готово,

person vancexu    schedule 31.10.2012
comment
Что такое вершины? В моем случае у меня есть координаты области интереса в виде массива rect_points Point2f. - person Mojo Jojo; 29.10.2015

Я нашел следующий пост очень полезным, чтобы сделать то же самое. http://answers.opencv.org/question/497/extract-a-rotatedrect-area/

Единственное предостережение заключается в том, что (а) «угол» здесь предполагается как поворот вокруг центра всего изображения (а не ограничивающей рамки) и (б) в последней строке ниже (я думаю) «rect.center» необходимо преобразовать в повернутое изображение (применив матрицу вращения).

    // rect is the RotatedRect 
    RotatedRect rect;
    // matrices we'll use
    Mat M, rotated, cropped;
    // get angle and size from the bounding box
    float angle = rect.angle;
    Size rect_size = rect.size;
    // thanks to http://felix.abecassis.me/2011/10/opencv-rotation-deskewing/
    if (rect.angle < -45.) {
        angle += 90.0;
        swap(rect_size.width, rect_size.height);
    }
    // get the rotation matrix
    M = getRotationMatrix2D(rect.center, angle, 1.0);
    // perform the affine transformation
    warpAffine(src, rotated, M, src.size(), INTER_CUBIC);
    // crop the resulting image
    getRectSubPix(rotated, rect_size, rect.center, cropped);
person kedar    schedule 25.04.2014

Если вам нужно сверхбыстрое решение, я предлагаю:

  • обрежьте Rect, охватывающий ваш RotatedRect rr.
  • поверните + переведите обратно обрезанное изображение, чтобы RotatedRect теперь был эквивалентен Rect. (используя warpAffine на произведении вращения и перевода матриц 3x3)
  • Сохраните эту область повернутого назад изображения (roi=Rect(Point(0,0), rr.size())).

Однако написание занимает немного времени, так как вам нужно вычислить комбинированное аффинное преобразование.

person Barney Szabolcs    schedule 26.11.2012

Если вас не волнует скорость и вы хотите создать быстрый прототип для любой формы области, вы можете использовать функцию openCV pointPolygonTest(), которая возвращает положительное значение, если точка внутри:

double pointPolygonTest(InputArray contour, Point2f pt, bool measureDist)

Простой код:

vector<Point2f> contour(4);
contour[0] = Point2f(-10, -10);
contour[1] = Point2f(-10, 10);
contour[2] = Point2f(10, 10);
contour[3] = Point2f(10, -10);    
Point2f pt = Point2f(11, 11);
an double res = pointPolygonTest(contour, pt, false);
if (res>0)
    cout<<"inside"<<endl;
else
    cout<<"outside"<<endl;
person Vlad    schedule 06.02.2014