I got some problem with compiling DLL file project. There are 2 files CDLL.h and CDLL.cpp:
CDLL.h:
#pragma once
namespace CDLL {
class CDLL
{
static unsigned char TransLut[256];
public:
__declspec(dllexport) void build_lookup_table ( int contr);
__declspec(dllexport) bool Contrast(HBITMAP * phBitmap, int iCount);
};
}
CDLL.cpp:
#include "Stdafx.h"
#include "CDLL.h"
#include <math.h>
#include <windows.h>
namespace CDLL
{
void CDLL::build_lookup_table(int contr)
{
float step, step_value;
for (int i=0; i < 256; i++)
TransLut[i] = i;
if (contr > 0)
{
unsigned int MinBin = contr;
unsigned int MaxBin = 255 - contr;
step = sqrt((double)contr)/contr;
step_value = 0.0;
for (int i = 0; i < MinBin; i++)
{
TransLut[i] = (unsigned char)step_value;
step_value += step;
}
step = 256.0f / (float)(MaxBin-MinBin);
for (int i = MinBin; i <= MaxBin; i++)
{
if (step_value > 255.0f)
{
step_value = 255.0f;
step = 0.0f;
}
TransLut[i] = (unsigned char)step_value;
step_value += step;
}
for (int i = MaxBin + 1; i < 256; i++)
TransLut[i] = 255;
}
else if (contr < 0)
{
step = (256.0+(float)(contr*2))/256.0;
step_value = (float)contr * -1.0;
for (int i = 0;i < 256; i++)
{
TransLut[i] = (unsigned char)step_value;
step_value += step;
}
}
}
bool CDLL::Contrast(HBITMAP * phBitmap, int iCount)
{
BITMAP bm;
BYTE * pBits;
RGBQUAD * pRgb;
WORD wByteCount;
int i, iPixels, gray;
build_lookup_table(iCount);
// Take BITMAP structure from HBITMAP
GetObject(*phBitmap, sizeof(BITMAP), &bm);
// Calculate bytes to read
wByteCount = bm.bmHeight * (2 * ((bm.bmWidth * bm.bmBitsPixel + 15) / 16));
// Alocate momory for bits od pixels and get pointers
pBits = (BYTE *) malloc(wByteCount);
GetBitmapBits(*phBitmap, wByteCount, pBits);
// Convert pointer to byte to pointer to RGBQUAD
pRgb = (RGBQUAD *) pBits;
// Operate on pixel's colors
iPixels = wByteCount / (bm.bmBitsPixel / 8);
for(int i = 0; i < iPixels; i++, pRgb++)
{
gray = (pRgb->rgbRed + pRgb->rgbGreen + pRgb->rgbBlue) / 3;
int k = TransLut[gray]-gray;
pRgb->rgbRed = min(pRgb->rgbRed + k, 255);
pRgb->rgbGreen = min(pRgb->rgbGreen + k, 255);
pRgb->rgbBlue = min(pRgb->rgbBlue + k, 255);
}
SetBitmapBits(*phBitmap, wByteCount, pBits);
return TRUE;
}
}
The thing I do not get why I get such an errors like:
error C2061: syntax error : identifier 'HBITMAP' CDLL.h
error C2511: 'bool CDLL::CDLL::Contrast(HBITMAP *,int)' : overloaded
member function not found in 'CDLL::CDLL' CDLL.cpp
Isn't #2 about the declaration of method in header file? How should I fix this one?
The HBITMAP type is a windows specific type. In your code it seems like you have forgotten to include the appropriate header. This may be the problem.
Related
I have tried to extract patches from an image parallelly with pixel shift/overlapping. I have written the CPU version of the code. But I could not able to convert the for loop which has an increment of pixel shift. I have given the part of the code where for loop is being used. CreatePatchDataSet function has the "for loop " which has an increment of pixel shift. Please help me out to convert this function into Cuda. I have provided the following code.
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>
#include <fstream>
#include <sstream>
#include <random>
#include <vector>
#include <omp.h>
using namespace std;
using namespace cv;
#define PATCH_SIZE (5)
#define PIXEL_SHIFT (2)
void ConvertMat2DoubleArray(cv::Mat input, double* output)
{
for (int i = 0; i < input.rows; i++)
{
double *src = input.ptr<double>(i);
for (int j = 0; j < input.cols; j++)
{
output[input.cols * input.channels() * i + input.channels() * j + 0] = src[j];
}
}
}
void GetNumOfPatch(const int width, const int height, const int patch_size, const int pixel_shift, int* num_of_patch, int* num_of_patch_col, int* num_of_patch_row) {
*num_of_patch_col = 0;
int len_nb = 0;
while (len_nb < width) {
if (len_nb != 0) {
len_nb += patch_size - (patch_size - pixel_shift);
}
else {
len_nb += patch_size;
}
(*num_of_patch_col)++;
}
len_nb = 0;
*num_of_patch_row = 0;
while (len_nb < height) {
if (len_nb != 0) {
len_nb += patch_size - (patch_size - pixel_shift);
}
else {
len_nb += patch_size;
}
(*num_of_patch_row)++;
}
*num_of_patch = (*num_of_patch_col) * (*num_of_patch_row);
}
void CreatePatchDataSet(double *original_data, double* patch_data, const int width, const int height, const int pixel_shift, const int patch_size, const int num_of_patch_col, const int num_of_patch_row) {
int counter_row = 0;
int num_of_patch_image = num_of_patch_row * num_of_patch_col;
for (int i = 0; i < height; i += pixel_shift) {
int counter_col = 0;
for (int j = 0; j < width; j += pixel_shift) {
//Get Low Resolution Image
for (int ii = 0; ii < patch_size; ii++) {
for (int jj = 0; jj < patch_size; jj++) {
if ((i + ii) < height && (j + jj) < width) {
patch_data[num_of_patch_image * (patch_size * ii + jj) + num_of_patch_col*counter_row + counter_col] = original_data[width*(i + ii) + (j + jj)];
}
else {
patch_data[num_of_patch_image * (patch_size * ii + jj) + num_of_patch_col*counter_row + counter_col] = 0.;
}
}
}
counter_col++;
if (counter_col == num_of_patch_col) {
break;
}
}
counter_row++;
if (counter_row == num_of_patch_row) {
break;
}
}
}
int main()
{
int ratio=2;
cv::Mat image = cv::imread("input_b2_128.tif", CV_LOAD_IMAGE_UNCHANGED);
cv::Mat imageH = cv::Mat(image.rows * ratio, image.cols * ratio, CV_8UC1);
cv::resize(image, imageH, cv::Size(imageH.cols, imageH.rows), 0, 0,
cv::INTER_LANCZOS4);
double* orgimageH = (double*)calloc(imageH.cols*imageH.rows*image.channels(), sizeof(double));
ConvertMat2DoubleArray(imageH, orgimageH);
int widthH = imageH.cols;
int heightH = imageH.rows;
int dimH = (int)PATCH_SIZE * (int)PATCH_SIZE* (int)image.channels();
int dimL = (int)PATCH_SIZE/ratio* (int)PATCH_SIZE/ratio * (int)image.channels();
//3. Create training data set=========================
int num_of_patch_image = 0;
int num_of_patch_col = 0;
int num_of_patch_row = 0;
GetNumOfPatch(widthH, heightH, (int)PATCH_SIZE, (int)PIXEL_SHIFT, &num_of_patch_image, &num_of_patch_col, &num_of_patch_row);
cout<<"patch numbers: \n " << num_of_patch_image << endl;
double* FY = (double*)calloc(dimH * num_of_patch_image, sizeof(double));
CreatePatchDataSet(orgimageH, FY, widthH, heightH, (int)PIXEL_SHIFT, (int)PATCH_SIZE, num_of_patch_col, num_of_patch_row);
free(orgimageH);
free(FY);
return 0;
}
The results I got for first 10 values in CPU version:
patch numbers:
16129
238,240,240,235,237,230,227,229,228,227
I have tried to convert this function to Kernel function using cuda:. But it goes into the infinite loop. As I am very new to this CUDA field, could you please help me to find out the problem in the code ?
__global__ void CreatePatchDataSet(double *original_data, double* patch_data, const int width, const int height, const int pixel_shift, const int patch_size, const int num_of_patch_col, const int num_of_patch_row) {
int num_of_patch_image = num_of_patch_row * num_of_patch_col;
int i = threadIdx.x + (blockDim.x*blockIdx.x);
int j = threadIdx.y + (blockDim.y*blockIdx.y);
while (i<height && j< width)
{
int counter_row = 0;
int counter_col = 0;
//Get Low Resolution Image
for (int ii = 0; ii < patch_size; ii++) {
for (int jj = 0; jj < patch_size; jj++) {
if ((i + ii) < height && (j + jj) < width) {
patch_data[num_of_patch_image * (patch_size * ii + jj) + num_of_patch_col*counter_row + counter_col] = original_data[width*(i + ii) + (j + jj)];
}
else {
patch_data[num_of_patch_image * (patch_size * ii + jj) + num_of_patch_col*counter_row + counter_col] = 0.;
}
}
}
counter_col++;
if (counter_col == num_of_patch_col) {
break;
}
counter_row++;
if (counter_row == num_of_patch_row) {
break;
}
}
i+= blockDim.x*gridDim.x;
j+= blockDim.y*gridDim.y;
}
int main()
{
int ratio=2;
cv::Mat image = cv::imread("input_b2_128.tif", CV_LOAD_IMAGE_UNCHANGED);
cv::Mat imageH = cv::Mat(image.rows * ratio, image.cols * ratio, CV_8UC1);
cv::resize(image, imageH, cv::Size(imageH.cols, imageH.rows), 0, 0, cv::INTER_LANCZOS4);
double *orgimageH = (double*)calloc(imageH.cols*imageH.rows*image.channels(), sizeof(double));
ConvertMat2DoubleArray(imageH, orgimageH);
int widthH = imageH.cols;
int heightH = imageH.rows;
//
int dimH = (int)PATCH_SIZE * (int)PATCH_SIZE* (int)image.channels();
int dimL = (int)PATCH_SIZE/ratio* (int)PATCH_SIZE/ratio * (int)image.channels();
//3. Create training data set=========================
int num_of_patch_image = 0;
int num_of_patch_col = 0;
int num_of_patch_row = 0;
GetNumOfPatch(widthH, heightH, (int)PATCH_SIZE, (int)PIXEL_SHIFT, &num_of_patch_image, &num_of_patch_col, &num_of_patch_row);
cout<<"patch numbers: \n " << num_of_patch_image << endl;
double* FY = (double*)calloc(dimH * num_of_patch_image, sizeof(double));
double *d_orgimageH;
gpuErrchk(cudaMalloc ((void**)&d_orgimageH, sizeof(double)*widthH*heightH));
double *d_FY;
gpuErrchk(cudaMalloc ((void**)&d_FY, sizeof(double)* dimH * num_of_patch_image));
gpuErrchk(cudaMemcpy(d_orgimageH , orgimageH , sizeof(double)*widthH*heightH, cudaMemcpyHostToDevice));
dim3 dimBlock(16, 16);
dim3 dimGrid;
dimGrid.x = (widthH + dimBlock.x - 1) / dimBlock.x;
dimGrid.y = (heightH + dimBlock.y - 1) / dimBlock.y;
CreatePatchDataSet<<<dimGrid,dimBlock>>>(d_orgimageH, d_FY, widthH, heightH, (int)PIXEL_SHIFT, (int)PATCH_SIZE, num_of_patch_col, num_of_patch_row);
gpuErrchk(cudaMemcpy(FY,d_FY, sizeof(double)*dimH * num_of_patch_image, cudaMemcpyDeviceToHost));
// cout<<"Hello world";
free(orgimageH);
free(FY);
cudaFree(d_FY);
cudaFree(d_orgimageH);
return 0;
}
Image I have used: [1]: https://i.stack.imgur.com/Ywg7p.png
i+= blockDim.x*gridDim.x;
j+= blockDim.y*gridDim.y;
is outside the while loop in your kernel. As i and j never change inside the while loop, it isn't stopping. There could be more problems here, but this is the most prominent one.
EDIT: Another one that I found, is that you have only one while over both i and j instead of one for each. You should probably use for loops like in your CPU code:
for (i = pixel_shift * (threadIdx.x + (blockDim.x*blockIdx.x));
i < height;
i += pixel_shift * blockDim.x * gridDim.x) {
for (j = ...; j < ...; j += ...) {
/* ... */
}
}
EDIT 2:
I could imagine this to be a good idea:
for (counter_row = threadIdx.y + blockDim.y * blockIdx.y;
counter_row < num_of_patch_row;
counter_row += blockDim.y * gridDim.y) {
i = counter_row * pixel_shift;
if (i > height)
break;
for (counter_col = threadIdx.x + blockDim.x * blockIdx.x;
counter_col < num_of_patch_col;
counter_col += blockDim.x * gridDim.x) {
j = counter_col * pixel_shift;
if (j > width)
break;
/* ... */
}
}
I have also exchanged the x/y fields of the execution parameters between the inner and the outer loop, as it seemed more appropriate considering that the x field is continuous in warps (memory access benefits).
Reference with this Question & answer by #Decade Moon
How can i use that method for generate image from byte array instead of image file.
i tried like below but nothing works. no image are shown
std::vector<char> data= std::vector<char>(imgx->Height * imgx->Width * 4);
int offset;
for (int row = 0; row < imgx->Height; row++)
{
for (int col = 0; col < imgx->Width; col++)
{
offset = (row * (int)(imgx->Width * 4)) + (col * 4);
data[offset] = 0x58; // Red
data[offset + 1] = 0x58; // Green
data[offset + 2] = 0x58; // Blue
data[offset + 3] = 0x58; // Alpha
}
};
My approach is little bit different from the reply you reffered to, but it works pretty well.
#include <wrl.h>
#include <robuffer.h>
using namespace Windows::UI::Xaml::Media::Imaging;
using namespace Windows::Storage::Streams;
using namespace Microsoft::WRL;
typedef uint8 byte;
byte* GetPointerToPixelData(IBuffer^ pixelBuffer, unsigned int *length)
{
if (length != nullptr)
{
*length = pixelBuffer ->Length;
}
// Query the IBufferByteAccess interface.
ComPtr<IBufferByteAccess> bufferByteAccess;
reinterpret_cast<IInspectable*>(pixelBuffer)->QueryInterface(IID_PPV_ARGS(&bufferByteAccess));
// Retrieve the buffer data.
byte* pixels = nullptr;
bufferByteAccess->Buffer(&pixels);
return pixels;
}
MainPage::MainPage()
{
InitializeComponent();
auto bitmap = ref new WriteableBitmap(50, 50);
image->Source = bitmap;
unsigned int length;
byte* sourcePixels = GetPointerToPixelData(bitmap->PixelBuffer, &length);
const unsigned int width = bitmap->PixelWidth;
const unsigned int height = bitmap->PixelHeight;
create_async([this, width, height, sourcePixels] {
byte* temp = sourcePixels;
// generate RED - BLUE gradient
for(unsigned int k = 0; k < height; k++) {
for (unsigned int i = 0; i < (width * 4); i += 4) {
int pos = k * (width * 4) + (i);
temp[pos] = (byte)(0xFF * k / (float)height); // B
temp[pos + 1] = 0x0; // G
temp[pos + 2] = 0xFF - (byte)(0xFF * k / (float)height); // R
temp[pos + 3] = 0xFF; // A
}
}
});
}
I made a program in C++ which calculates the mandelbrot-set. Now I want to visualize it (save it in a picture). But when I try to save a 64k picture some problems come up. So what is the best way to save a picture of the pixels or at least to visual it?
Edit:
When I want to create a for Example 64K (61440 * 34560) image there will be the error "Access violation while writing at the position 0x0..." (originally on German and translated) and the program stops. This error appears with very high resolution. On lower resolutions the program works as it is supposed to.
#include <SFML\Graphics.hpp>
#include <stdlib.h>
#include <complex>
#include <cmath>
#include <thread>
//4K : 3840 * 2160
//8K : 7680 * 4320
//16K: 15360 * 8640
//32K: 30720 * 17280
//64K: 61440 * 34560
//128K:122880 * 69120
const unsigned long width = 61440; //should be dividable by ratioX & numberOfThreads!
const unsigned long height = 34560; //should be dividable by ratioY & numberOfThreads!
const unsigned int maxIterations = 500;
const unsigned int numberOfThreads = 6;
const int maxWidth = width / 3;
const int maxHeight = height / 2;
const int minWidth = -maxWidth * 2;
const int minHeight = -maxHeight;
const double ratioX = 3.0 / width;
const double ratioY = 2.0 / height;
sf::Image img = sf::Image();
int getsGreaterThan2(std::complex<double> z, int noIterations) {
double result;
std::complex<double> zTmp = z;
std::complex<double> c = z;
for (int i = 1; i != noIterations; i++) {
zTmp = std::pow(z, 2) + c;
if (zTmp == z) {
return 0;
}
z = std::pow(z, 2) + c;
result = std::sqrt(std::pow(z.real(), 2) + std::pow(z.imag(), 2));
if (result > 2) {
return i;
}
}
return 0;
}
void fillPixelArrayThreadFunc(int noThreads, int threadNr) { //threadNr ... starts from 0
double imgNumber;
double realNumber;
double tmp;
long startWidth = ((double)width) / noThreads * threadNr + minWidth;
long endWidth = startWidth + width / noThreads;
for (long x = startWidth; x < endWidth; x++) {
imgNumber = x * ratioX;
for (long y = minHeight; y < maxHeight; y++) {
realNumber = y * ratioY;
long xArray = x - minWidth;
long yArray = y - minHeight;
tmp = getsGreaterThan2(std::complex<double>(imgNumber, realNumber), maxIterations);
if (tmp == 0) {
img.setPixel(xArray, yArray, sf::Color(0, 0, 0, 255));
}
else {
img.setPixel(xArray, yArray, sf::Color(tmp / maxIterations * 128, tmp / maxIterations * 128, tmp / maxIterations * 255, 255));
}
}
}
}
int main() {
img.create(width, height, sf::Color::Black);
std::thread *threads = new std::thread[numberOfThreads];
for (int i = 0; i < numberOfThreads; i++) {
threads[i] = std::thread(std::bind(fillPixelArrayThreadFunc, numberOfThreads, i));
}
for (int i = 0; i < numberOfThreads; i++) {
threads[i].join();
}
img.saveToFile("filename.png");
return 1;
}
Your program fails during the call img.create(width, height, sf::Color::Black);.
When you step into the sf::Image::create function you end up here where the newPixels vector is created, this simply fails when width * height is too big as in your case:
////////////////////////////////////////////////////////////
void Image::create(unsigned int width, unsigned int height, const Color& color)
{
if (width && height)
{
// Create a new pixel buffer first for exception safety's sake
std::vector<Uint8> newPixels(width * height * 4);
^61440* ^34560 = 8'493'465'600 bytes !!
Conclusion: SFML cannot handle huge images.
I am using a lookup table to convert raw pixel data between color spaces and coding variants. This is the definition of my LUT:
typedef struct
{
unsigned char data[3];
} rgb;
rgb LUTYUVTORGB[256][256][256];
It is initialized like this:
// loop through all possible values
for (int in_1 = 0; in_1 < 256; in_1++) {
for (int in_2 = 0; in_2 < 256; in_2++) {
for (int in_3 = 0; in_3 < 256; in_3++) {
int out_1, out_2, out_3;
// LUT YUV -> RGB
// convert to rgb (http://softpixel.com/~cwright/programming/colorspace/yuv/)
out_1 = (int)(in_1 + 1.4075 * (in_3 - 128));
out_2 = (int)(in_1 - 0.3455 * (in_2 - 128) - (0.7169 * (in_3 - 128)));
out_3 = (int)(in_1 + 1.7790 * (in_2 - 128));
// clamp values
if (out_1 < 0) { out_1 = 0; } else if (out_1 > 255) { out_1 = 255; }
if (out_2 < 0) { out_2 = 0; } else if (out_2 > 255) { out_2 = 255; }
if (out_3 < 0) { out_3 = 0; } else if (out_3 > 255) { out_3 = 255; }
// set values in LUT
LUTYUVTORGB[in_1][in_2][in_3].data[0] = (unsigned char)out_1;
LUTYUVTORGB[in_1][in_2][in_3].data[1] = (unsigned char)out_2;
LUTYUVTORGB[in_1][in_2][in_3].data[2] = (unsigned char)out_3;
}
}
}
The LUT is then applied to copy the raw pixel data to a QImage():
for (int y = 0; y < h; y++) {
for (int x = 0; x < w; x++) {
xpos = (y*w + x); // don't calculate 3 times
buff[x * 3 + 0] = psImage->comps[0].data[xpos];
buff[x * 3 + 1] = psImage->comps[1].data[xpos];
buff[x * 3 + 2] = psImage->comps[2].data[xpos];
}
memcpy(image.scanLine(y), buff, bytes_per_line);
}
The values of the LUT are static, and have to be initialized every time the programm starts. Is there any way to initialize it via the preprocessor? Or would it be recommendable to save it in a file?
EDIT: The conversion is used in a time critical video application where every frame has to be processed individually.
Thanks very much in advance!
I have created one dimensional array for this table, it is convenient to save and load such array. I think using this array in runtime wont decrease performance. But I didn't test it for performance differences.
#include <stdio.h>
#include <stdlib.h>
#define LUTSIZE 0x1000000
typedef struct
{
unsigned char data[3];
} rgb;
rgb *LUT;
inline int LUT_index(int in_1, int in_2, int in_3) {
return in_1 * 0x10000 + in_2 * 0x100 + in_3 * 0x1;
}
inline rgb LUT_value(int in_1, int in_2, int in_3) {
return LUT[LUT_index(in_1,in_2,in_3)];
}
void save(rgb *LUT, char* fileName) {
FILE* file = fopen(fileName,"wb");
int index;
for (int in_1 = 0; in_1 < 256; in_1++) {
for (int in_2 = 0; in_2 < 256; in_2++) {
for (int in_3 = 0; in_3 < 256; in_3++) {
int out_1, out_2, out_3;
// LUT YUV -> RGB
// convert to rgb (http://softpixel.com/~cwright/programming/colorspace/yuv/)
out_1 = (int)(in_1 + 1.4075 * (in_3 - 128));
out_2 = (int)(in_1 - 0.3455 * (in_2 - 128) - (0.7169 * (in_3 - 128)));
out_3 = (int)(in_1 + 1.7790 * (in_2 - 128));
// clamp values
if (out_1 < 0) { out_1 = 0; } else if (out_1 > 255) { out_1 = 255; }
if (out_2 < 0) { out_2 = 0; } else if (out_2 > 255) { out_2 = 255; }
if (out_3 < 0) { out_3 = 0; } else if (out_3 > 255) { out_3 = 255; }
index = LUT_index(in_1,in_2,in_3);
// set values in LUT
LUT[index].data[0] = (unsigned char)out_1;
LUT[index].data[1] = (unsigned char)out_2;
LUT[index].data[2] = (unsigned char)out_3;
}
}
}
fwrite((void*)LUT, sizeof(rgb),LUTSIZE,file);
fclose(file);
}
void read(rgb *LUT, char* fileName) {
FILE* file = fopen(fileName, "rb");
fread((void*)LUT,sizeof(rgb),LUTSIZE,file);
fclose(file);
}
int main(int argc, char *argv[])
{
LUT = (rgb*)malloc(LUTSIZE * sizeof(rgb));
save(LUT, "LUT_data");
rgb testValue = LUT_value(5,3,7);
printf("%d %d %d\n", testValue.data[0], testValue.data[1], testValue.data[2]);
read(LUT, "LUT_data");
testValue = LUT_value(5,3,7);
printf("%d %d %d\n", testValue.data[0], testValue.data[1], testValue.data[2]);
free(LUT);
}
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;
}
EDIT:
I don't need CvtColor function, I need to use that one factorial function.
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.
Try cvtColor(src, bwsrc, CV_RGB2GRAY);
http://docs.opencv.org/2.4/modules/imgproc/doc/miscellaneous_transformations.html (look for cvtColor).
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);