Get line as two point on cvCanny() in OpenCV - arrays

Sorry for stupid question. I want get line as two point, but cvCanny() put line in CvArr (image matrix). I can parse matrix for get line, but it slowly... I use JavaCV. Code example
IplImage image;
IplImage gray;
IplImage dst;
gray = cvCreateImage( cvGetSize(image), IPL_DEPTH_8U, 1 );
dst = cvCreateImage( cvGetSize(image), IPL_DEPTH_8U, 1 );
cvCanny(gray, dst, 100, 200, 3);
Image result (dst object)

If you need to find a line inside a picture, use HoughLines
Of course, it is best to use it on the result of the edge detection (canny)

Related

OpenCV canny; output image is pure gray

I am learning opencv and reading a book and following examples. The book introduced the canny filter. However there is some problem with my output. As an input image I have given a 512x512 gray scale image but the filter output is pure gray image. Here is the image:
This is the input image.
And this is the output image.
And here is the snippets:
#include <opencv\cv.h>
#include <opencv2\highgui\highgui.hpp>
#include "Resources.h"
IplImage* doCanny(
IplImage* in,
double lowThresh,
double highThresh,
double aperture
) {
if (in->nChannels != 1)
{
return 0; // Canny only handle gray scale images.
}
IplImage* out = cvCreateImage(
CvSize(cvGetSize(in)),
IPL_DEPTH_8U,
1
);
cvCanny(in, out, lowThresh, highThresh, aperture);
return out;
}
int main(int argc, char** argv)
{
IplImage* image = cvLoadImage(IMAGE_FRUIT);
IplImage* output = doCanny(image, 200, 201, 1);
cvNamedWindow("Canny", CV_WINDOW_AUTOSIZE);
cvShowImage("Canny", output);
cvWaitKey(0);
cvReleaseImage(&output);
cvDestroyWindow("Canny");
return 0;
}
Visual Studio 2015, OpenCV version 2.4.13
I think if you step through your code, you will realize the cvCanny function never gets triggered, the returned output from doCanny is a null pointer.
OpenCV's Canny edge detection algorithm only accepts gray scale image, which is why the original code has the "if (in->nChannels != 1)" check, so you need to convert your input image into a grayscale image first.
// Convert to grayscale first
IplImage* gray_image = cvCreateImage(cvGetSize(image), IPL_DEPTH_8U, 1);
cvCvtColor(image, gray_image, CV_BGR2GRAY);
// Perform Canny
IplImage* output = doCanny(gray_image, 200, 201, 3);
Additional, I think your "aperture" parameter for cvCanny is also invalid, try to use the default value 3 (or 5, 7), and you should be able to see the result.
I would also recommend using the C++ interface instead of the deprecated C interface.

openCV get subimage in C

I am using OpenCV for image manipulation in C. Please forgive me if this question is answered in the documentation, but I have found the OpenCV docs to be pretty badly formed and difficult to read.
I have an CvMat* that i have extracted from an image file as below:
CvMat* mat = cvLoadImageM((char*) filename, CV_LOAD_IMAGE_COLOR);
What I need to do is get a subimage of that by cropping out a certain bounded region. A logical command for this might be:
CvMat* subMat = cvGetSubImage(mat, minx, maxx, miny, maxy);
where minx, maxx, miny, and maxy define the boundaries of the cropped region. Is there a built in way to do this easily?
Take a look at http://nashruddin.com/OpenCV_Region_of_Interest_(ROI)/
In which the tutorial does the following on a Region of Interest:
cvSetImageROI(img1, cvRect(10, 15, 150, 250));
IplImage *img2 = cvCreateImage(cvGetSize(img1),
img1->depth,
img1->nChannels);
cvCopy(img1, img2, NULL);
cvResetImageROI(img1);
OpenCV has built in capabilities for setting the region which you care about and copying that region out of an image, just as you want to achieve.
If you want a sub-pixel accurate rectangular section of a src image use cvGetRectSubPix or cv::getRectSubPix (this creates an individual copy of all the data, this is not a ROI!)
Example:
cv::Size size(dst_width,dst_height);
cv::Point2f center(src_centerx,src_center_y);
cv::Mat dst;
cv::getRectSubPix(src,size, center,dst,CV_8U);
Generally this is done by cropping an ROI (region of interest). This blog post goes into some detail on cropping:
/* load image */
IplImage *img1 = cvLoadImage("elvita.jpg", 1);
/* sets the Region of Interest
Note that the rectangle area has to be __INSIDE__ the image */
cvSetImageROI(img1, cvRect(10, 15, 150, 250));
/* create destination image
Note that cvGetSize will return the width and the height of ROI */
IplImage *img2 = cvCreateImage(cvGetSize(img1),
img1->depth,
img1->nChannels);
/* copy subimage */
cvCopy(img1, img2, NULL);
/* always reset the Region of Interest */
cvResetImageROI(img1);
To convert between IplImage (legacy OpenCV) and cvMat (OpenCV 2.x), simply use the cvMat constructor or look at this question for more methods.

Return type as Array of IPlImage

I spend the whole morning today searching for a way to save an array of images in IplImage type in openCV and failed.
This is what I am trying to do :
IplImage* GetThresholdedImage(IplImage* img) {
IplImage* imageTest[2];
IplImage* imgHSV = cvCreateImage(cvGetSize(img), 8, 3); // hold the resulted HSV image
cvCvtColor(img, imgHSV, CV_BGR2HSV); // convert the coming image from the camera from RGB format to HSV (Hue, Saturation, Value)
imageTest[0] = cvCreateImage(cvGetSize(img), 8, 1); //hold the thresholded image of the yellow color
imageTest[1] = cvCreateImage(cvGetSize(img), 8, 1); //hold the thresholded image of the red color
cvSmooth(imgHSV, imgHSV, CV_GAUSSIAN, 11, 11); //smooth the image to remove the noise from the image
cvInRangeS(imgHSV, cvScalar(24, 100, 150), cvScalar(34, 255, 255),
imageTest[0]); //this function filter out the colors in this range (This is a yellow color)
cvInRangeS(imgHSV, cvScalar(172, 100, 150), cvScalar(179, 255, 255),
imageTest[1]); //this function filter out the colors in this range (This is a red color)
cvReleaseImage(&imgHSV);
return *imageTest;
}
Now when I try to return the array in the main in order to process it -->
IplImage *thresholdedImage;// = cvCreateImage(cvGetSize(frame), 8, 1); // to store the thresholded image
IplImage *yellow = cvCreateImage(cvGetSize(frame), 8, 1);
IplImage *red = cvCreateImage(cvGetSize(frame), 8, 1);
//===========================================
// start creating three windows to show the video after being thresholded, after it passes the contour function and the final video
cvNamedWindow("display", CV_WINDOW_AUTOSIZE);
cvNamedWindow("Threshold", CV_WINDOW_AUTOSIZE);
cvNamedWindow("contoured", CV_WINDOW_AUTOSIZE);
while (key != 'q') { // grab the video unless the user press q button
frame = cvQueryFrame(capture);
if (!frame) {
break;
}
//start the actual video processing on real-time frames
//first output of the threshold method
thresholdedImage = GetThresholdedImage(frame);
yellow = *thresholdedImage;
red = *thresholdedImage++;
//insert the resulted frame from the above function into the find contour function
cvFindContours(yellow, storage, &contours, sizeof(CvContour),
CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, cvPoint(0, 0));
cvFindContours(red, storage, &contours, sizeof(CvContour),
CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, cvPoint(0, 0));
however it gives me error !!!
any help is appreciated , thank you
An array of pointers to IplImage would be IplImage**. Also note, that you have to provide the buffer from the outside, as you can't return a pointer to local (non-static) data.
void GetImages(IplImage** images, unsigned int num) {
// assign pointers here
images[0] = ...
images[1] = ...
}
IplImage *images[2];
GetImage(images, 2);
As an alternative, you could as well create the array within your function using new or malloc and return the pointer to it. Just ensure you delete/free it later on.
IplImage **CreateImages(unsigned int num) {
IplImage **images = new IplImage*[num];
// assign again
images[0] = ...
return images;
}
Also ensure you free the images, once you're done with them. So you shouldn't use the approach you used above (increasing the pointer). Instead simply use array syntax to access n-th element.
Your code fails due to returning only a single pointer to the first image instead of the actual array.

OpenCV cvCanny memory exception

I am trying to do the examples in the OpenCV book and I got to the part regarding cvCanny. I am trying to use it, but I keep getting a memory exception error of
Unhandled exception at 0x75d8b760 in Image_Transform.exe: Microsoft C++ exception: cv::Exception at memory location 0x0011e7a4..
I have also looked at another post that was similar to this question, but it did not help for me as I got the same error each time. Any help is greatly appreciated and the source code for the function is located below.
void example2_4(IplImage* img)
{
// Create windows to show input and ouput images
cvNamedWindow("Example 2-4 IN", CV_WINDOW_AUTOSIZE);
cvNamedWindow("Example 2-4 OUT", CV_WINDOW_AUTOSIZE);
// Display out input image
cvShowImage("Example 2-4 IN", img);
// Create an image to hold our modified input image
IplImage* out = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 3);
// Do some smoothing
//cvSmooth(img, out, CV_GAUSSIAN, 3, 3);
// Do some Edge detection
cvCanny(img, out, 10, 20, 3);
// Show the results
cvShowImage("Example 2-4 OUT", out);
// Release the memory used by the transformed image
cvReleaseImage(&out);
// Wait for user to hit a key then clean up the windows
cvWaitKey(0);
cvDestroyWindow("Example 2-4 IN");
cvDestroyWindow("Example 2-4 OUT");
}
int main()
{
// Load in an image
IplImage* img = cvLoadImage("images/00000038.jpg");
// Run the transform
example2_4(img);
// clean the image from memory
cvReleaseImage(&img);
return 0;
}
You forgot to say if you are able to see the original image being displayed on the screen.
I never get tired of telling people that checking the return of functions is a must!
Consider IplImage* img = cvLoadImage("images/00000038.jpg"); , how can you tell if this function succeeded or not? As far as I can tell, the error you are having might be from a function failing prior to cvCanny() being called.
Anyway, I recently posted a code that uses cvCanny to improve circle detection. You can check that code and see what you are doing differently.
EDIT:
Your problem in this case is that you are passing to cvCanny input and output as a 3 channel image, when it takes only a single channel image. Check the docs:
void cvCanny(const CvArr* image, CvArr* edges, double threshold1, double threshold2, int aperture_size=3)
Implements the Canny algorithm for edge detection.
Parameters:
* image – Single-channel input image
* edges – Single-channel image to store the edges found by the function
* threshold1 – The first threshold
* threshold2 – The second threshold
* aperture_size – Aperture parameter for the Sobel operator (see Sobel)
So, change your code to:
// Create an image to hold our modified input image
IplImage* out = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 1);
// Do some smoothing
//cvSmooth(img, out, CV_GAUSSIAN, 3, 3);
IplImage* gray = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 1);
cvCvtColor(img, gray, CV_BGR2GRAY);
// Do some Edge detection
cvCanny(gray, out, 10, 20, 3);

Convert image document to black and white with OpenCV

I'm new to OpenCV and image processing and I'M not sure how to solve my problem.
I have a photo of document made in iPhone and I want to convert that document to black and white. I tried to use threshold but the text was not so good (a little blurry and unreadable). I'd like to text looks same as on the original image, only black, and background will be white. What can I do?
P.S. When I made a photo of part of the document, where text is quite big, then result is ok.
I will be grateful for any help.
Here are the example image I use and the result:
My attemp, maybe a little more readable than yours:
IplImage * pRGBImg = 0;
pRGBImg = cvLoadImage(input_file.c_str(), CV_LOAD_IMAGE_UNCHANGED);
if(!pRGBImg)
{
std::cout << "ERROR: Failed to load input image" << std::endl;
return -1;
}
// Allocate the grayscale image
IplImage * pGrayImg = 0;
pGrayImg = cvCreateImage(cvSize(pRGBImg->width, pRGBImg->height), pRGBImg->depth, 1);
// Convert it to grayscale
cvCvtColor(pRGBImg, pGrayImg, CV_RGB2GRAY);
// Dilate
cvDilate(pGrayImg, pGrayImg, 0, 0.2);
cvThreshold(pGrayImg, pGrayImg, 30, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);
cvSmooth(pGrayImg, pGrayImg, CV_BLUR, 2, 2);
cvSaveImage("out.png", pGrayImg);
Threshold image is used for different purposes.
If u just want to convert it to b/w image just do this. USing openCV 2.2
cv::Mat image_name = cv::imread("fileName", 0);
the second parameter 0 tells to read a color image as b/w image.
And if you want to save as a b/w image file.
code this
cv::Mat image_name = cv::imread("fileName", 0);
cv::imwrite(image_name, "bw_filename.jpg");
Using Adaptive Gaussian Thresholding is a good idea here. This will also enhance the quality of text written in the image.
You can do that by simply giving the command:
AdaptiveThreshold(src_Mat, dst_Mat, Max_value, Adaptive_Thresholding_Method, Thresholding_type, blocksize, C);

Resources