Ask Your Question
1

Drawing lines from Canny?

asked 2015-02-14 17:02:12 -0500

KevinWorkman gravatar image

I posted this on StackOverflow here, but after only getting a few views, I've decided to crosspost here.

I'm a complete novice when it comes to OpenCV, so this is probably a dumb question.

I'm just trying to get something basic up and running- I want to draw the edges detected by the Canny algorithm directly on the image coming in. I currently have this:

I'm displaying the edge data from Canny directly, but now I want to get rid of the black and just show the white, on the image being processed.

I've tried googling things like "using binary image as alpha mask", but after a day of reading tutorials and trying everything I can find, I'm still not sure I know what's going on. OpenCV seems very powerful, so this is probably a pretty easy thing to do, so I'm hoping somebody can point me in the right direction.

Here's the code I'm using, most of which has been copied from the examples:

public Mat onCameraFrame(CvCameraViewFrame inputFrame) {

    Mat rgba = inputFrame.rgba();
    org.opencv.core.Size sizeRgba = rgba.size();

    Mat rgbaInnerWindow;


    int rows = (int) sizeRgba.height;
    int cols = (int) sizeRgba.width;

    int left = cols / 8;
    int top = rows / 8;

    int width = cols * 3 / 4;
    int height = rows * 3 / 4;

    //get sub-image
    rgbaInnerWindow = rgba.submat(top, top + height, left, left + width);

    //create edgesMat from sub-image
    Imgproc.Canny(rgbaInnerWindow, edgesMat, 100, 100);

    //copy the edgesMat back into the sub-image
   Imgproc.cvtColor(edgesMat, rgbaInnerWindow, Imgproc.COLOR_GRAY2BGRA, 4);

    rgbaInnerWindow.release();

    return rgba;
}

If anybody can point me to a basic example that does what I want, I'd be very grateful!

OpenCV edge detection screenshot

edit retag flag offensive close merge delete

Comments

Hi,I don't know why do you choice canny operation to detect line.You should choice Hough line or LSD, i think they are best choice.

wuling gravatar imagewuling ( 2015-02-15 02:15:30 -0500 )edit

@wuling I chose canny because it was the first result for googling "OpenCV edge detection".

KevinWorkman gravatar imageKevinWorkman ( 2015-02-15 10:15:38 -0500 )edit

I think wuling just got confused with "lines" , since actually you want to detect edges not lines ;)

Guanta gravatar imageGuanta ( 2015-02-15 10:21:50 -0500 )edit

:)Never mind,do what you want

wuling gravatar imagewuling ( 2015-02-15 17:05:55 -0500 )edit

2 answers

Sort by ยป oldest newest most voted
4

answered 2015-02-15 06:47:14 -0500

Guanta gravatar image

So, you want to set all edges, which you got from Canny, to white in your original image. Here you can make use of bitwise_or (cvtColor only converts your color space):

Input image:

Input image

Canny output:

Canny output

Bitwise or of the input image with Canny:

bitwise_or

And here the code (I just used Python, however it should work similarly in C++ and should also work similarly in Java):

import cv2, numpy as np
img = cv2.imread('cat.jpg')
# it seems canny can only deal with 1 channel 8-bit images
# --> let's take the mean and convert to 8bit (could also use cvtColor instead)  
canny = cv2.Canny(np.mean(img, axis=2).astype(np.uint8), 50, 200)
cv2.imwrite('canny.png', canny)
# for bitwise_or the shape needs to be the same, so we need to add an axis, 
# since our input image has 3 axis while the canny output image has only one 2 axis
out = np.bitwise_or(img, canny[:,:,np.newaxis])
cv2.imwrite('out.png', out)

I used here numpys' bitwise_or function, but it exists also directly in OpenCV, see: http://docs.opencv.org/modules/core/doc/operations_on_arrays.html?highlight=bitwise_or#cv2.bitwise_or


Alternative 1: Another way would be to create a new mat as large as the input image, set everything to 255. Invert the canny output image (bitwise_not) and use this as mask for copyTo, i.e. img.copyTo(white_image, canny_invert);

Alternative 2: You can also do everything by hand, i.e. you could also just loop over the image and make a look up in your mask and set the image accordingly.

edit flag offensive delete link more
0

answered 2015-02-23 13:20:47 -0500

KevinWorkman gravatar image

Eventually I used the setTo() method to set the color, and then the copyTo() method to copy that color back to the original Mat:

 public Mat onCameraFrame(CvCameraViewFrame inputFrame) {

    Mat rgba = inputFrame.rgba();
    org.opencv.core.Size sizeRgba = rgba.size();

    int rows = (int) sizeRgba.height;
    int cols = (int) sizeRgba.width;

    int left = cols / 8;
    int top = rows / 8;
    int width = cols * 3 / 4;
    int height = rows * 3 / 4;

    //get sub-image
    Mat rgbaInnerWindow = rgba.submat(top, top + height, left, left + width);

    //create edgesMat from sub-image
    Imgproc.Canny(rgbaInnerWindow, edgesMat, 100, 100);

    Mat colorEdges = new Mat();
    Mat killMe = colorEdges;
    edgesMat.copyTo(colorEdges);
    Imgproc.cvtColor(colorEdges, colorEdges, Imgproc.COLOR_GRAY2BGRA);

    colorEdges = colorEdges.setTo(greenScalar, edgesMat);
    colorEdges.copyTo(rgbaInnerWindow, edgesMat);

    killMe.release();
    colorEdges.release();
    rgbaInnerWindow.release();

    return rgba;
}
edit flag offensive delete link more
Login/Signup to Answer

Question Tools

1 follower

Stats

Asked: 2015-02-14 17:02:12 -0500

Seen: 3,674 times

Last updated: Feb 23 '15