Ask Your Question
1

All points above a line

asked 2016-02-18 09:45:50 -0600

willoughby gravatar image

updated 2020-08-16 12:15:14 -0600

I have an image and a line bisecting that image (with a slope between -1.0 and 1.0). Is there an effective way to access all points above the line?

edit retag flag offensive close merge delete

Comments

1

Not efficient way:

  • iterate through the image
  • test for the sign of the line equation
Eduardo gravatar imageEduardo ( 2016-02-18 11:49:49 -0600 )edit

use affine transform (rotation given by your line) to change axis

LBerger gravatar imageLBerger ( 2016-02-18 12:56:28 -0600 )edit

2 answers

Sort by ยป oldest newest most voted
2

answered 2016-02-19 16:12:13 -0600

Tetragramm gravatar image

The image is stored row major, so you want to go down each row. The equation of a line is y=m*x+b, but we need to invert it. x = y/m-b/m.

if(m > 0)
{
    for(int y = 0; y<MIN(b,rows); ++y)
    {
        for(int x = 0; x < MIN(cols, (y-b)/m); ++x)
        {
            //Do Stuff Here
        }
    }
}
else if(m == 0) //Trivial case
else
{
    for(int y = 0; y<MIN(b, rows); ++y)
    {
        for(int x = MAX(0, (y-b)/m); x<cols; ++x)
        {
            //Do Stuff Here
        }
    }
}

Note: This assumes your equation is in image space, which has +y as the bottom of the image.

Can someone else double check this? I don't have a compiler handy.

edit flag offensive delete link more
1

answered 2016-02-20 10:39:01 -0600

Eduardo gravatar image

updated 2016-02-20 10:42:13 -0600

Nice piece of code @Tetragramm !

I modified your code by "randomly" swapping the elements until it works as dealing with the 2 frame origins gave me some headaches and I didn't manage to make work your original code with the different line equations.

I also added my "brute force approach".

The result with your (modified) approach:

The result with pt1(20, 15), pt2(600, 385) in normal 2D frame: image description

The result with pt1(50, 421), pt2(621, 77) in normal 2D frame: image description

The result with pt1(0, 600), pt2(621, 77) in normal 2D frame: image description

The result with pt1(0, -50), pt2(621, 253) in normal 2D frame: image description

The corresponding code:

#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>


//@link: http://answers.opencv.org/question/87979/all-points-above-a-line/
//@author: Tetragramm
void drawPoints(cv::Mat &img, const double m, const double b)
{
    //Optimal way
    int rows = img.rows, cols = img.cols;
    if(m > 0)
    {
        for(int y = 0; y < MAX(b,rows); ++y)
        {
            for(int x = MAX(0, (y-b)/m); x<cols; ++x)
            {
                //Do Stuff Here
                img.at<cv::Vec3b>(y, x) = cv::Vec3b(255,0,0);
            }
        }
    }
    else if(m == 0) {
        //Trivial case
    }
    else
    {
        for(int y = 0; y < MIN(b, rows); ++y)
        {
            for(int x = 0; x < MIN(cols, (y-b)/m); ++x)
            {
                //Do Stuff Here
                img.at<cv::Vec3b>(y, x) = cv::Vec3b(255,0,0);
            }
        }
    }
}

void calculateLineEquation(const cv::Point &pt1, const cv::Point &pt2, double &a, double &b)
{
    a = (pt2.y - pt1.y) / (double) (pt2.x - pt1.x);
    b = pt1.y - a*pt1.x;
}

void myDrawPoints(cv::Mat &img, const double a, const double b)
{
    //BruteForce
    for(int i = 0; i < img.rows; i++)
    {
        for(int j = 0; j < img.cols; j++)
        {
            double x = j, y = img.rows - i;
            if(a * x + b - y > 0)
            {
                img.at<cv::Vec3b>(i, j) = cv::Vec3b(255,0,0);
            }
            else if(a * x + b - y < 0)
            {
                img.at<cv::Vec3b>(i, j) = cv::Vec3b(0,255,0);
            }
        }
    }
}

int main()
{
    //Coordinates in regular 2D frame
    //int x1 = 20, x2 = 600;
    //int y1 = 15, y2 = 385;
    //int x1 = 50, x2 = 621;
    //int y1 = 421, y2 = 77;
    //int x1 = 0, x2 = 621;
    //int y1 = 600, y2 = 77;
    int x1 = 0, x2 = 621;
    int y1 = -50, y2 = 253;
    cv::Mat img1 = cv::Mat::zeros(480, 640, CV_8UC3), img2 = cv::Mat::zeros(480, 640, CV_8UC3), 
        img3 = cv::Mat::zeros(480, 640, CV_8UC3);
    cv::Point pt1(x1, img1.rows - y1), pt2(x2, img1.rows - y2);

    cv::line(img3, pt1, pt2, cv::Scalar(0,0,255), 1);

    double a = 0.0;
    double b = 0.0;

    calculateLineEquation(pt1, pt2, a, b);
    std::cout << "Line equation in image space, slope a=" << a << " ; ordinate at origin b=" << b << std::endl;
    drawPoints(img1, a, b);

    calculateLineEquation(cv::Point(x1,y1), cv::Point(x2,y2), a, b);
    std::cout << "Regular 2D frame, slope a=" << a << " ; ordinate at origin b=" << b << std::endl;
    myDrawPoints(img2, a, b);

    cv::imshow("img1", img1);
    cv::imwrite("points_above_line.png ...
(more)
edit flag offensive delete link more

Comments

Glad I could help. Thanks for doing that, I was busy and away from my normal computer yesterday.

Tetragramm gravatar imageTetragramm ( 2016-02-20 12:03:45 -0600 )edit

Question Tools

1 follower

Stats

Asked: 2016-02-18 09:45:50 -0600

Seen: 458 times

Last updated: Feb 20 '16