Generwp
Generwp

Reputation: 514

OpenCV color image to gray trouble

I'm new to OpenCV and I'm trying to proccess the image from the directory, make it black and white (grayscale) and then write it down to another file. But the output image is quite different from what I expected. Maybe you can help me and indicate the errors in code?

#include <iostream>
#include <opencv2/opencv.hpp>
#include <conio.h>
#include <string.h>
#include <string>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/core/core.hpp>
#include <stdio.h>
#include <stdlib.h>
#include "cuda_runtime.h"
#include "device_launch_parameters.h"

using namespace std;

void faktorial(int InSize, char *DataIn, char *DataOut)// заголовок функции
{
    for(int i = 0,  j = 0; i < InSize; i += 4, j++)
    {
        DataOut[j] = (DataIn[i] + DataIn[i + 1] + DataIn[i + 2]) / 3;
    }

}

int main() 
{        
        char* c = "E:\henrik-evensen-castle-valley-v03.jpg";

        printf("Input source of image\n Example of right directory file: E:\henrik-evensen-castle-valley-v03.jpg\n Your try:\n");
        char *tbLEN;
        tbLEN = new char [1024];

        cin.getline(tbLEN,1024);

        cout << tbLEN;


        IplImage* image;
        image = cvLoadImage(tbLEN, 1);
        int height1 = image->height;
        int width1 = image->width;
        int step = image->widthStep;
        int SizeIn = step*height1;
        char* DatIn = image->imageData;

        IplImage *image2 = cvCreateImage(cvSize(image->width, image->height), IPL_DEPTH_8U, 1);
        char* DatOut = image2->imageData;

        faktorial(SizeIn, DatIn, DatOut);

        cvNamedWindow("Imagecolor");
        cvShowImage("Imagecolor", image);

        cvNamedWindow("Gray");
        cvShowImage("Gray", image2);
        cvWaitKey(0);
        return 0;
}

Input Image Output Image

EDIT: I don't need CvtColor function, I need to use that one factorial function.

Upvotes: 0

Views: 325

Answers (3)

Miki
Miki

Reputation: 41765

In faktorial you assume you have 3 channels. So you need to increase i by 3, and not by 4. Also, you need to convert char* data to uchar* data, so that accumulation works ok:

You end up with:

void faktorial(int InSize, uchar *DataIn, uchar *DataOut)
{
    for (int i = 0, j = 0; i < InSize; i += 3, j++)
    {
        DataOut[j] = (DataIn[i] + DataIn[i + 1] + DataIn[i + 2]) / 3;
    }
}

You can easily extend this to multiple channels, like:

void faktorial2(int InSize, int nChannels, uchar *DataIn, uchar *DataOut)
{
    for (int i = 0, j = 0; i < InSize; i += nChannels, j++)
    {
        int accum = 0;
        for (int c = 0; c < nChannels; ++c)
        {
            accum += DataIn[i + c];
        }
        DataOut[j] = uchar(accum / nChannels);
    }
}

You in general need also to take image stride into account:

void faktorial3(int rows, int cols, int in_step, int in_channels, int out_step, uchar *in, uchar *out)
{
    for (int r = 0; r < rows; ++r)
    {
        for (int c = 0; c < cols; ++c)
        {
            int accum = 0;
            for (int i = 0; i < in_channels; ++i)
            {
                accum += in[r*in_step + c * in_channels + i];
            }
            out[r*out_step + c] = uchar(accum / in_channels);
        }
    }
}

Here the full code with the calls:

#include <opencv2/opencv.hpp>
using namespace std;

void faktorial3(int rows, int cols, int in_step, int in_channels, int out_step, uchar *in, uchar *out)
{
    for (int r = 0; r < rows; ++r)
    {
        for (int c = 0; c < cols; ++c)
        {
            int accum = 0;
            for (int i = 0; i < in_channels; ++i)
            {
                accum += in[r*in_step + c * in_channels + i];
            }
            out[r*out_step + c] = uchar(accum / in_channels);
        }
    }
}

void faktorial(int InSize, uchar *DataIn, uchar *DataOut)
{
    for (int i = 0, j = 0; i < InSize; i += 3, j++)
    {
        DataOut[j] = (DataIn[i] + DataIn[i + 1] + DataIn[i + 2]) / 3;
    }

}

void faktorial2(int InSize, int nChannels, uchar *DataIn, uchar *DataOut)
{
    for (int i = 0, j = 0; i < InSize; i += nChannels, j++)
    {
        int accum = 0;
        for (int c = 0; c < nChannels; ++c)
        {
            accum += DataIn[i + c];
        }
        DataOut[j] = uchar(accum / nChannels);
    }
}

int main()
{
    char tbLEN[] = "D:\\SO\\img\\barns.jpg";

    IplImage* image;
    image = cvLoadImage(tbLEN, 1);

    IplImage *image2 = cvCreateImage(cvSize(image->width, image->height), IPL_DEPTH_8U, 1);

    int height1 = image->height;
    int width1 = image->width;
    int step = image->widthStep;
    int SizeIn = step*height1;
    int nChannels = image->nChannels;
    uchar* DatIn = (uchar*)image->imageData;
    uchar* DatOut = (uchar*)image2->imageData;

    faktorial(SizeIn, DatIn, DatOut);
    //faktorial2(SizeIn, nChannels, DatIn, DatOut);
    //faktorial3(image->height, image->width, image->widthStep, image->nChannels, image2->widthStep, (uchar*)image->imageData, (uchar*)image2->imageData);

    cvNamedWindow("Imagecolor");
    cvShowImage("Imagecolor", image);

    cvNamedWindow("Gray");
    cvShowImage("Gray", image2);
    cvWaitKey(0);
    return 0;
}

Remember that C api is obsolete. You should switch to C++ api.

Upvotes: 1

MBo
MBo

Reputation: 80127

Your faktorial is intended for 4 byte per pixel images (and it doesn't take into account possible line padding).

Loaded from JPG image has 3 byte per pixel, that is why you see 4 shifted ghosts. You can modify faktorial or just convert loaded image to 4-byte format

 image = cvLoadImage(tbLEN, 1);
 cvtColor(image, image, CV_RGB2RGBA); 

Upvotes: 0

Leonardo Alves Machado
Leonardo Alves Machado

Reputation: 2837

Try cvtColor(src, bwsrc, CV_RGB2GRAY); http://docs.opencv.org/2.4/modules/imgproc/doc/miscellaneous_transformations.html (look for cvtColor).

Upvotes: 1

Related Questions