Machine Vision

cancel
Showing results for 
Search instead for 
Did you mean: 

Convert an image to grayscale in C

Solved!
Go to solution

Hello. I want to convert an image, acquired from webcam, to grayscale in C, using myRIO. I have a webcam connected to myRIO, simple image acquisition is working, but I cannot find a solution to convert the image to grayscale. I don't get any errors at Building or at Run Configuration.

 

This is the image written in folder: (black) 

capturedImage4.png

 

The code is here:

#include <stdio.h>
#include <stdbool.h>
#include "MyRio.h"
#include <nivision.h>
#include <NIIMAQdx.h>

#define CAM_NAME    "cam1"
#define CAPTURED_IMAGE_PATH     "./capturedImage4.png"

#define WINDOW_NUMBER    15    // Image Display Window Number
#define IMAQDX_ERROR_MESSAGE_LENGTH    256

bool Log_Vision_Error(int errorValue);
bool Log_Imaqdx_Error(IMAQdxError errorValue);

int main(int argc, char **argv)
{
#if 1
    NiFpga_Status status;

    printf("\n ++ ImageAcquisitionAndDisplayExample \n");

    	Image* captureImage = NULL;
    	Image* processedImage;


    	IMAQdxSession session = 0;
    /*
     * Open the myRIO NiFpga Session.
     * This function MUST be called before all other functions. After this call
     * is complete the myRIO target will be ready to be used.
     */
    status = MyRio_Open();
    if (MyRio_IsNotSuccess(status))
    {
        return status;
    }

    // Create the Image Buffer
    	captureImage = imaqCreateImage(IMAQ_IMAGE_HSL, 0);
    	processedImage = imaqCreateImage(IMAQ_IMAGE_HSL, 0);
    	imaqSetImageSize(processedImage, 640, 480);


    	// Open a session to the selected camera
    	if (Log_Imaqdx_Error(IMAQdxOpenCamera(CAM_NAME, IMAQdxCameraControlModeController, &session)))
    		goto cleanup;

    	// Acquire an image
    	if (Log_Imaqdx_Error(IMAQdxSnap(session, captureImage)))
    		goto cleanup;

    	// Process the Captured image here.
    	// Grayscale

    	if (Log_Imaqdx_Error(imaqExtractColorPlanes(captureImage, 1, NULL, NULL, processedImage )))
    	    		goto cleanup;


    	// Write the captured image to the file
    	Log_Vision_Error(imaqWriteVisionFile(processedImage, CAPTURED_IMAGE_PATH, NULL));



    cleanup:
    	//Close the Camera session
    	IMAQdxCloseCamera (session);

    	// Dispose the image
    	imaqDispose(captureImage);
    	imaqDispose(processedImage);
    	

    	printf("\n -- ImageAcquisitionAndDisplayExample \n");
    	return 0;


   
    status = MyRio_Close();
#endif
}

    bool Log_Imaqdx_Error(IMAQdxError errorValue)
    {
    	if (errorValue) {
    		char errorText[IMAQDX_ERROR_MESSAGE_LENGTH];
    		IMAQdxGetErrorString(errorValue, errorText, IMAQDX_ERROR_MESSAGE_LENGTH);
    		printf("\n %s ", errorText);
    		return true;
    	}
    	return false;
    }

    // Print the VISION Error Message
    bool Log_Vision_Error(int errorValue)
    {
    	if ( (errorValue != TRUE) && (imaqGetLastError() != ERR_SUCCESS)) {
    		char *tempErrorText = imaqGetErrorText(imaqGetLastError());
    		printf("\n %s ", tempErrorText);
    		imaqDispose(tempErrorText);
    		return true;
    	}
    	return false;
    }
0 Kudos
Message 1 of 5
(7,036 Views)

To be clear, by "simple image acquisition is working," you mean you can get regular images to save to disk using the Snap and appear as you'd like.  It's not until you run this line:

 

if (Log_Imaqdx_Error(imaqExtractColorPlanes(captureImage, 1, NULL, NULL, processedImage )))
    	    		goto cleanup;

that you run into any issues?  At that point, you only pull out the all black image? 

 

I know you're trying to use C.  But, why don't we take a quick look at an example in LabVIEW?  Check out this KB: http://digital.ni.com/public.nsf/allkb/ED42C55C29B9B34C862570A60079952E  While the language is different, we're looking at the same general API and we should be able to figure out what's going on and translate that to C for you.

 

In the VI Snippet, we start by creating an image buffer named "orig" and read from a file path to fill that image buffer.  We also create an image buffer for the HSL data type.  That allows us to pull the Hue, Saturation, and Luminance planes rather than the RGB planes.

 

From there, we cast the image in "orig" to the HSL type and place it in the "hsl" buffer.  We pass this modified image to the Extract Color Planes VI.  At this point, we extract the Luminance plane and get something grayscale from there.

 

Also, check out this document: http://www.ni.com/pdf/manuals/322567a.pdf  It provides information about all of the potential calls.  On page 2-20, it discusses the imaqExtractColorPlanes function call.

 

int = imaqExtractColorPlanes(const Image* image, ColorMode mode, Image* plane1, Image* plane2, Image* plane3)

Looking at your call, that means

image = captureImage

mode = 1

plane1 = NULL

plane2 = NULL

plane 3 = processedImage

 

In the documentation for mode, "The color space from which the function extracts the planes. Valid options are IMAQ_RGB, IMAQ_HSL, IMAQ_HSV, and IMAQ_HSI. For more information about color spaces, see the IMAQ Vision User Manual."  Let's try changing that away from 1 to being one of those types.  It looks like you're trying to use 1 in place of IMAQ_HSL and pull the third plane as the luminance plane.  Is that correct?

0 Kudos
Message 2 of 5
(7,009 Views)

 


BoKnows wrote:

To be clear, by "simple image acquisition is working," you mean you can get regular images to save to disk using the Snap and appear as you'd like.  It's not until you run this line:

 

if (Log_Imaqdx_Error(imaqExtractColorPlanes(captureImage, 1, NULL, NULL, processedImage )))
    	    		goto cleanup;

that you run into any issues?  At that point, you only pull out the all black image? 

 

 


Yes, without this part of code, I can get a regular image and it appear on the disk. After I insert that code, I get the black image.

 



BoKnows wrote:

 

 

 

In the documentation for mode, "The color space from which the function extracts the planes. Valid options are IMAQ_RGB, IMAQ_HSL, IMAQ_HSV, and IMAQ_HSI. For more information about color spaces, see the IMAQ Vision User Manual."  Let's try changing that away from 1 to being one of those types.  It looks like you're trying to use 1 in place of IMAQ_HSL and pull the third plane as the luminance plane.  Is that correct?


Sorry for this, I forgot to modify the code that I uploaded here. In Eclipse it was correct written, like this:

if (Log_Imaqdx_Error(imaqExtractColorPlanes(captureImage, IMAQ_HSL, NULL, NULL, processedImage )))
    	    		goto cleanup;
I put the 1 instead of IMAQ_HSL only to see what happens and I forgot to change back. But id doesn't work neither this way with IMAQ_HSL, I get the same black image.

 

About, LabVIEW, I understand what you say, I also made a VI to see what functions are used:
Capture.PNG
Here I saw the imaqExtractColorPlanes planes and I searched it in Vision's Help. I still don't understand why is not working because it's the same code translated from LabVIEW to C.

 

 

 

0 Kudos
Message 3 of 5
(6,962 Views)

The LabVIEW code you posted doesn't include anything to send the image to a file.  I'm curious if we're running into issues at this stage.  If we comment out the code to convert to greyscale, does the original image write to the file correctly or are you only viewing it in the tests where you say it works?

 

I'm assuming the LabVIEW code you posted works to complete the task.  It's slightly different than what I posted.  But, as long as things are working I'm not too concerned with that. 

0 Kudos
Message 4 of 5
(6,933 Views)
Solution
Accepted by topic author DC20

@BoKnows wrote:

The LabVIEW code you posted doesn't include anything to send the image to a file.  I'm curious if we're running into issues at this stage.  If we comment out the code to convert to greyscale, does the original image write to the file correctly or are you only viewing it in the tests where you say it works?

 

I'm assuming the LabVIEW code you posted works to complete the task.  It's slightly different than what I posted.  But, as long as things are working I'm not too concerned with that. 


The code works now. The problem was here:  

 

if (Log_Imaqdx_Error(imaqExtractColorPlanes(captureImage, 1, NULL, NULL, processedImage )))

 Instead of Log_Imaqdx_Error, it must be Log_Vision_Error.

0 Kudos
Message 5 of 5
(6,918 Views)