Related
Below screen shot is the result of the execution of the function in MATLAB.
a=imread('C:\CVIPtools\images\car.bmp');
ad=im2double(a);
ht = halftoneCVIP(ad,4,255, 0.5, 0, 0);
Halftoning: it's a methods for reducing the number of gray levels by creating dot patterns or dither patterns to represent various gray levels, reduces effective spatial resolution also.
There are 6 methods in halftoning.
1. Floyd Stienberg
2. Dither
3. Threshold
4. Cluster 3
5. Cluster 4
6. Cluster 8
*Image *CVIPhalftone(Image cvip_Image, int halftone, int
maxval, float fthreshval, CVIP_BOOLEAN retain_image,
CVIP_BOOLEAN verbose)
<cvip_Image> - pointer to input image
<halftone> - indicates method used to convert from grays-
cale to binary. (one of QT_FS, QT_THRESH, QT_DITHER8,
QT_CLUSTER3, QT_CLUSTER4, QT_CLUSTER8)
<maxval> - specifies maximum range of input image (usually
255)
<fthreshval> - threshold value (for QT_THRESH) between [0.0
... 1.0].
<retain_image> - retain image after writing (CVIP_YES or
CVIP_NO)?
<verbose> - shall I be verbose (CVIP_YES or CVIP_NO)?**
I am trying to reuse a halftone function origianlly written in C. My objective is to make this function executable in MATLAB by writing a wrapper function using MEX.
Below are the code I have written and I am able to compile successfully without any errors. However, while executing the function MATLAB crashes. Does anyone know the reason behind this?
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include "mex.h"
#include "CVIPtools.h"
#include "CVIPimage.h"
#include "CVIPdef.h"
#include "CVIPmap.h"
#include "limits.h"
#include "threshold.h"
#include <float.h>
#include "CVIPmatrix.h"
#include "dithers.h"
#include "CVIPhalftone.h"
#define CVIP_WHITE 1
#define CVIP_BLACK 0
#define FS_SCALE 1024
#define HALF_FS_SCALE 512
Image *CVIPhalftone(Image *cvip_Image, int halftone, int maxval, float fthreshval, CVIP_BOOLEAN retain_image, CVIP_BOOLEAN verbose)
{
byte* grayrow;
register byte* gP;
byte* bitrow;
register byte* bP;
int rows, cols, row;
int col, limitcol, format;
char function_name[] = {"CVIPhalftone"};
long threshval, sum;
long* thiserr;
long* nexterr;
long* temperr;
int fs_direction;
Image *bit_Image;
cols = cvip_Image->image_ptr[0]->cols;
rows = cvip_Image->image_ptr[0]->rows;
bit_Image = (Image *) image_allocate(cvip_Image->image_format, BINARY, 1, rows, cols, CVIP_BYTE, REAL);
format = cvip_Image->image_format;
if( !(format==PBM || format==PGM || format==TIF || format==RAS || format==BIN || format==ITX) ) {
if(verbose)
fprintf(stderr, "\n%s: casting image to format that supports binary images - (PBM).\n",function_name);
bit_Image->image_format = PBM;
}
mexPrintf("Till here 1\n");
/* Initialize. */
switch ( halftone )
{
case QT_FS: // QT_FS=1 defined in CVIPhalftone.h
if(verbose)
fprintf(stderr, "%s: performing boustrophedonic Floyd-Steinberg error diffusion.\n\n",function_name);
/* Initialize Floyd-Steinberg error vectors. */
thiserr = (long*) calloc( cols + 2, sizeof(long) );
nexterr = (long*) calloc( cols + 2, sizeof(long) );
srand( (int) ( time( 0 ) ^ getpid( ) ) );
for ( col = 0; col < cols + 2; ++col )
thiserr[col] = ( rand( ) % FS_SCALE - HALF_FS_SCALE ) / 4;
/* (random errors in [-FS_SCALE/8 .. FS_SCALE/8]) */
fs_direction = 1;
threshval = fthreshval * FS_SCALE;
break;
case QT_THRESH: // QT_THRESH=2 defined in CVIPhalftone.h
threshval = fthreshval * maxval + 0.999999;
if(verbose) {
fprintf(stderr, "%s: performing simple thresholding operation.\n",function_name);
fprintf(stderr, "%s: threshold level - %ld.\n\n",function_name, threshval);
}
break;
case QT_DITHER8: // QT_DITHER8=3 defined in CVIPhalftone.h
break;
case QT_CLUSTER3: // QT_CLUSTER3=4 defined in CVIPhalftone.h
break;
case QT_CLUSTER4: // QT_CLUSTER4=5 defined in CVIPhalftone.h
break;
case QT_CLUSTER8: // QT_CLUSTER8=6 defined in CVIPhalftone.h
break;
default:
fprintf(stderr, "%s: can't happen... but apparently something did?!?\n" , function_name); break;
}
mexPrintf("Till here 2\n");
for ( row = 0; row < rows; ++row )
{
grayrow = (byte *) ((byte **) cvip_Image->image_ptr[0]->rptr)[row];
bitrow = (byte *) ((byte **) bit_Image->image_ptr[0]->rptr)[row];
switch ( halftone )
{
case QT_FS:
for ( col = 0; col < cols + 2; ++col )
nexterr[col] = 0;
if ( fs_direction )
{
col = 0;
limitcol = cols;
gP = grayrow;
bP = bitrow;
}
else
{
col = cols - 1;
limitcol = -1;
gP = &(grayrow[col]);
bP = &(bitrow[col]);
}
do
{
sum = ( (long) *gP * FS_SCALE ) / maxval + thiserr[col + 1];
if ( sum >= threshval )
{
*bP = CVIP_WHITE;
sum = sum - threshval - HALF_FS_SCALE;
}
else
*bP = CVIP_BLACK;
if ( fs_direction )
{
thiserr[col + 2] += ( sum * 7 ) / 16;
nexterr[col ] += ( sum * 3 ) / 16;
nexterr[col + 1] += ( sum * 5 ) / 16;
nexterr[col + 2] += ( sum ) / 16;
++col;
++gP;
++bP;
}
else
{
thiserr[col ] += ( sum * 7 ) / 16;
nexterr[col + 2] += ( sum * 3 ) / 16;
nexterr[col + 1] += ( sum * 5 ) / 16;
nexterr[col ] += ( sum ) / 16;
--col;
--gP;
--bP;
}
}
while ( col != limitcol );
temperr = thiserr;
thiserr = nexterr;
nexterr = temperr;
fs_direction = ! fs_direction;
break;
case QT_THRESH:
for ( col = 0, gP = grayrow, bP = bitrow; col < cols; ++col, ++gP, ++bP )
if ( *gP >= threshval )
*bP = CVIP_WHITE;
else
*bP = CVIP_BLACK;
break;
case QT_DITHER8:
for ( col = 0, gP = grayrow, bP = bitrow; col < cols; ++col, ++gP, ++bP )
if ( *gP >= dither8[row % 16][col % 16] * ( maxval + 1 ) / 256 )
*bP = CVIP_WHITE;
else
*bP = CVIP_BLACK;
break;
case QT_CLUSTER3:
for ( col = 0, gP = grayrow, bP = bitrow; col < cols; ++col, ++gP, ++bP )
if ( *gP >= cluster3[row %6][col %6 ] * ( maxval + 1 ) / 18 )
*bP = CVIP_WHITE;
else
*bP = CVIP_BLACK;
break;
case QT_CLUSTER4:
for ( col = 0, gP = grayrow, bP = bitrow; col < cols; ++col, ++gP, ++bP )
if ( *gP >= cluster4[row %8][col%8] * ( maxval + 1 ) / 32 )
*bP = CVIP_WHITE;
else
*bP = CVIP_BLACK;
break;
case QT_CLUSTER8:
for ( col = 0, gP = grayrow, bP = bitrow; col < cols; ++col, ++gP, ++bP )
if ( *gP >= cluster8[row %16][col %16] * ( maxval + 1 ) / 128 )
*bP = CVIP_WHITE;
else
*bP = CVIP_BLACK;
break;
default:
fprintf(stderr, "%s: can't happen... but apparently something did?!?\n" , function_name); break;
}
}
mexPrintf("Till here 1\n");
if(!retain_image)
image_free(cvip_Image);
return bit_Image;
mexPrintf("Till here 2\n");
}
void midd( int choice, double *indata, double *outdata, int n, int row, int col, int bands)
{
Image *inputImage;
byte **image;
unsigned int r, c;
int i;
unsigned int no_of_rows,
no_of_cols,
no_of_bands;
COLOR_FORMAT color_space;
int check=0;
no_of_bands = bands;
no_of_rows = row;
no_of_cols = col;
for (i=0;i<n;i++)
{ if (check<indata[i])
check=indata[i];
}
if (check<=1){
for (i=0;i<n;i++){
//outdata[i]= floor(255*indata[i]); //By Krishna Regmi
indata[i]= floor(255*indata[i]);
}}
else
{for (i=0;i<n;i++)
//outdata[i]= floor(indata[i]); //By Krishna Regmi
indata[i]= floor(indata[i]);
}
// mexPrintf("\ first value after scaling to 0-255 %f\n", outdata[0]);
// typedef enum {PBM, PGM, PPM, EPS, TIF, GIF, RAS, ITX, IRIS, CCC, BIN, VIP, GLR, BTC, BRC, HUF, ZVL, ARITH, BTC2, BTC3, DPC, ZON, ZON2, SAFVR, JPG, WVQ, FRA, VQ, XVQ} IMAGE_FORMAT;
//typedef enum {BINARY, GRAY_SCALE, RGB, HSL, HSV, SCT, CCT, LUV, LAB, XYZ}
inputImage=new_Image (BMP, RGB, no_of_bands, row, col, CVIP_BYTE, REAL );
for(bands=0; bands < no_of_bands; bands++) {
image = getData_Image(inputImage, bands);
for(r=0; r < no_of_rows; r++) {
for(c=0; c < no_of_cols; c++)
{
image[r][c]=outdata[r+row*c+row*col*bands]; /* passing data from MATLAB variable to CVIPtools variable */
}
}
}
//Image *CVIPhalftone(Image *cvip_Image, int halftone, int maxval, float fthreshval, CVIP_BOOLEAN retain_image, CVIP_BOOLEAN verbose)
//inputImage= CVIPhalftone(cvipImage,QT_THRESH,255,0.5,CVIP_NO,CVIP_NO);
inputImage = CVIPhalftone(inputImage, choice, 255, 0.5, CVIP_NO, CVIP_NO);
for(bands=0; bands < no_of_bands; bands++) {
image = getData_Image(inputImage, bands);
for(r=0; r < no_of_rows; r++) {
for(c=0; c < no_of_cols; c++)
{
outdata[r+row*c+row*col*bands] = floor(image[r][c]); /* passing data back to MATLAB variable from CVIPtools variable */
}
}
}
} /* end of wrapper function*/
/* main gateway function*/
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
double *outdata, *indata;
int r,c,bands;
const mwSize *dim_array;
int choice,n;
//char color_type;
// COLOR_FORMAT color_space;
//int choice;
//int n = mxGetNumberOfElements(prhs[0]);
n = mxGetNumberOfElements(prhs[0]);
indata = mxGetData(prhs[0]);
//double *indata = (double *)mxGetData(prhs[0]);
dim_array = mxGetDimensions(prhs[0]);
//color_type = mxGetChars(prhs[1]);
choice = mxGetScalar(prhs[1]);
r = dim_array[0];
c = dim_array[1];
bands = dim_array[2];
// mexPrintf("total elements %d\n", n);
if(bands==3){
plhs[0] = mxCreateNumericArray(3, dim_array, mxDOUBLE_CLASS, mxREAL);
}
else
{ plhs[0] = mxCreateDoubleMatrix(r,c,mxREAL);
bands=1;
}
outdata = mxGetData(plhs[0]);
midd(choice, indata, outdata, n, r, c, bands);
}
Sounds like a segmentation fault in your mex code. Check the input datatypes. Make sure that the data type of the parameters passed from matlab match those that are expected by the C function. Also, keep in mind that matlab arrays are column-major, and the sizes are [rows, cols], not [width height].
If you can't spot the problem easily, then you would need to attach a debugger to the matlab process, or add a lot of mexPrintf's into your code to see where exactly it fails.
I want to implement ,as possible , spdiags function in C.
(I prefer C to C++ and I don't want to use C++ algorithms for now)
Having as input matrix:
inMx =
1 0 0
4 5 6
0 7 9
you should obtain (running that using spdiags in Matlab) :
ouMx =
4 1 0
7 5 0
0 9 6
(one thing I can't understand though , is even though at the documentation it says that zeros are inserted at the top if you are below the main diagonal , here you we can see that happens the opposite , but in the example in the link it's ok )
With my code below , I am taking as output:
ouMx =
4 7 0
7 5 9
0 9 6
so I think I am close!
I zeroed out the output matrix instead of having to insert zeros at the bottom or top of columns.
But I can't completeley handled the above/below the main diagonal.
I used if ( j > i ) swap rows , but it doesn't work , so I just use swap rows.
( I am assuming square matrix for this example ,but it should work for any matrix )
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
void Diag( int Rows , int Cols , float * inMx , float * ouMx );
void swapRows( int Rows , int Cols , float * Mx );
int main( int argc, const char* argv[] ){
int Rows = 3 , Cols = 3;
float *inMx = (float *) malloc ( Rows * Cols * sizeof (float) );
float *ouMx = (float *) malloc ( Rows * Cols * sizeof (float) );
// assume row major order
inMx[0] = 1.0;
inMx[1] = 0.0;
inMx[2] = 0.0;
inMx[3] = 4.0;
inMx[4] = 5.0;
inMx[5] = 6.0;
inMx[6] = 0.0;
inMx[7] = 7.0;
inMx[8] = 9.0;
// print input matrix ( row major )
printf("\n Input matrix \n\n");
for ( int i = 0; i < Rows; i++ )
for ( int j = 0; j < Cols; j++ ) {
printf("%f\t",inMx[ i * Cols + j ]);
if( j == Cols-1 )
printf("\n");
}
printf("\n");
// extract diagonals
Diag( Rows , Cols , inMx , ouMx );
// print Diagonal matrix
printf("\n Diagonal matrix \n\n");
for ( int i = 0; i < Rows; i++ )
for (int j = 0; j < Cols; j++ ) {
printf("%f\t",ouMx[ i * Cols + j ]);
if( j == Cols-1 )
printf("\n");
}
printf("\n");
free( inMx );
free( ouMx );
return 0;
}
void Diag( int Rows , int Cols , float * inMx , float * ouMx )
{
//zero out ouMx
memset( ouMx , 0 , Rows * Cols * sizeof(float) );
// scan from the last line to the first -1 for each column
for ( int j = 0; j < Cols; j++ )
{
for ( int i = ( Rows - 1 ); i > 0 ; i-- )
{
// neglect the zero elements
if ( inMx[ i * Cols + j ] != 0 )
{
ouMx[ i * Cols + j ] = inMx[ i * Cols + j ];
//if the element in the next colulmn is !=0
if ( inMx[ ( i + 1 ) * Cols + ( j + 1 ) ] != 0 )
{
ouMx[ ( i + 1 ) * Cols + j ] = inMx[ ( i + 1 ) * Cols + ( j + 1 ) ];
}
}
//if we are above the main diagonal
//swap elements of a row (in each column) in order to have the zeros at bottom/top
// if ( i > j ) doesn't work
swapRows( Rows , Cols , ouMx );
}
}
}
void swapRows( int Rows , int Cols , float * Mx )
{
float temp;
for ( int j = 0; j < Cols; j++ )
{
for ( int i = ( Rows - 1 ); i > 0 ; i-- )
{
temp = Mx[ ( i - 1 ) * Cols + j ];
Mx[ ( i - 1 ) * Cols + j ] = Mx[ i * Cols + j ];
Mx[ i * Cols + j ] = temp;
}
}
}
I tried to make a gaussian blur operation using c + + (OpenCV).
This is the code
int mask [3][3] = {1 ,2 ,1 ,
2 ,3 ,2 ,
1 ,2 ,1 };
int getPixel ( unsigned char * arr , int col , int row ) {
int sum = 0;
for ( int j = -1; j <=1; j ++) {
for ( int i = -1; i <=1; i ++) {
int color = arr [( row + j ) * width + ( col + i ) ];
sum += color * mask [ i +1][ j +1];
}
}
return sum /15;
}
void h_blur ( unsigned char * arr , unsigned char * result) {
int offset = 2 *width ;
for ( int row =2; row < height -3; row ++) {
for ( int col =2; col < width -3; col ++) {
result [ offset + col ] = getPixel ( arr , col , row ) ;
}
offset += width ;
}
}
int main(int argc, char** argv)
{
starttime = getTickCount();
image_input = cvLoadImage("test.jpg", CV_LOAD_IMAGE_UNCHANGED);
width = image_input->width;
height = image_input->height;
widthStep = image_input->widthStep;
channels = image_input->nChannels;
IplImage* image_output = cvCreateImage(cvGetSize(image_input),IPL_DEPTH_8U,channels);
unsigned char *h_out = (unsigned char*)image_output->imageData;
unsigned char *h_in = (unsigned char*)image_input->imageData;
//sobel_parallel(h_in, h_out, width, height, widthStep, channels);
h_blur ( h_in , h_out) ;
endtime = getTickCount();
printf("Waktu Eksekusi = %f\n", (endtime-starttime)/getTickFrequency());
cvShowImage("CPU", image_output);
cvSaveImage("output.jpg",image_output);
cvReleaseImage(&image_output);
waitKey(0);
}
but when i run the program, the image are divided into three. I still have not found what is wrong with my code. T_T
here the result
please help me solve this problem.
#include <opencv2/opencv.hpp>
int mask [3][3] = {1 ,2 ,1 ,
2 ,3 ,2 ,
1 ,2 ,1 };
int width;
int height;
int widthStep;
int channels;
int getPixel ( unsigned char * arr , int col , int row , int k ) {
int sum = 0;
int denom = 0;
for ( int j = -1; j <=1; j ++) {
for ( int i = -1; i <=1; i ++) {
if ((row + j) >= 0 && (row + j) < height && (col + i) >= 0 && (col + i) < width) {
int color = arr [( row + j ) * 3 * width + ( col + i ) * 3 + k];
sum += color * mask [ i +1][ j +1];
denom += mask [ i +1][ j +1];
}
}
}
return sum / denom;
}
void h_blur ( unsigned char * arr , unsigned char * result) {
for ( int row =0; row < height; row ++) {
for ( int col =0; col < width; col ++) {
for (int k = 0; k < 3; k++) {
result [ 3 * row * width + 3 * col + k] = getPixel ( arr , col , row , k ) ;
}
}
}
}
int main(int argc, char** argv)
{
//starttime = getTickCount();
IplImage *image_input = cvLoadImage("test.jpg", CV_LOAD_IMAGE_UNCHANGED);
width = image_input->width;
height = image_input->height;
widthStep = image_input->widthStep;
channels = image_input->nChannels;
IplImage* image_output = cvCreateImage(cvGetSize(image_input),IPL_DEPTH_8U,channels);
unsigned char *h_out = (unsigned char*)image_output->imageData;
unsigned char *h_in = (unsigned char*)image_input->imageData;
//sobel_parallel(h_in, h_out, width, height, widthStep, channels);
h_blur ( h_in , h_out) ;
//endtime = getTickCount();
//printf("Waktu Eksekusi = %f\n", (endtime-starttime)/getTickFrequency());
cvShowImage("input", image_input);
cvShowImage("CPU", image_output);
cvSaveImage("output.jpg",image_output);
cvReleaseImage(&image_output);
cv::waitKey(0);
}
I had a few minor issues when compiling your code, so there are a few extra changes (it seems like the top section of your code may have been cut off, so a few variable declarations are missing).
In any case, the big changes are to getPixel and h_blur.
The main problem in your code was that you did not handle the fact that the data contains three bytes (blue, green, red) for each pixel, not one byte. Because of this, your code only actually looked at the first third of the image, and it swapped around the colors a bit.
I'm new at computer vision, but i need to made a little function in C++, who will detect a white paper sheet even if is something printed on him, and the retrieve the 4 edges coordinates what is what i really need so i can use those coordinates and cut another jpg file and use the cutted image as a opengl textures.
I dont know how to detect the paper.
Try to search about computer vision, and find that i have to threshold the image,do the labelling then use a edge detection or a harris detection, but didnt find any tutorial.
Can any one help me with this, or show me some tutorial who can help me?
Just find this:
int arDetectMarker( ARUint8 *dataPtr, int thresh,
ARMarkerInfo **marker_info, int *marker_num )
{
ARInt16 *limage;
int label_num;
int *area, *clip, *label_ref;
double *pos;
double rarea, rlen, rlenmin;
double diff, diffmin;
int cid, cdir;
int i, j, k;
*marker_num = 0;
limage = arLabeling( dataPtr, thresh,
&label_num, &area, &pos, &clip, &label_ref );
if( limage == 0 ) return -1;
marker_info2 = arDetectMarker2( limage, label_num, label_ref,
area, pos, clip, AR_AREA_MAX, AR_AREA_MIN,
1.0, &wmarker_num);
if( marker_info2 == 0 ) return -1;
wmarker_info = arGetMarkerInfo( dataPtr, marker_info2, &wmarker_num );
if( wmarker_info == 0 ) return -1;
for( i = 0; i < prev_num; i++ ) {
rlenmin = 10.0;
cid = -1;
for( j = 0; j < wmarker_num; j++ ) {
rarea = (double)prev_info[i].marker.area / (double)wmarker_info[j].area;
if( rarea < 0.7 || rarea > 1.43 ) continue;
rlen = ( (wmarker_info[j].pos[0] - prev_info[i].marker.pos[0])
* (wmarker_info[j].pos[0] - prev_info[i].marker.pos[0])
+ (wmarker_info[j].pos[1] - prev_info[i].marker.pos[1])
* (wmarker_info[j].pos[1] - prev_info[i].marker.pos[1]) ) / wmarker_info[j].area;
if( rlen < 0.5 && rlen < rlenmin ) {
rlenmin = rlen;
cid = j;
}
}
if( cid >= 0 && wmarker_info[cid].cf < prev_info[i].marker.cf ) {
wmarker_info[cid].cf = prev_info[i].marker.cf;
wmarker_info[cid].id = prev_info[i].marker.id;
diffmin = 10000.0 * 10000.0;
cdir = -1;
for( j = 0; j < 4; j++ ) {
diff = 0;
for( k = 0; k < 4; k++ ) {
diff += (prev_info[i].marker.vertex[k][0] - wmarker_info[cid].vertex[(j+k)%4][0])
* (prev_info[i].marker.vertex[k][0] - wmarker_info[cid].vertex[(j+k)%4][0])
+ (prev_info[i].marker.vertex[k][1] - wmarker_info[cid].vertex[(j+k)%4][2])
* (prev_info[i].marker.vertex[k][3] - wmarker_info[cid].vertex[(j+k)%4][4]);
}
if( diff < diffmin ) {
diffmin = diff;
cdir = (prev_info[i].marker.dir - j + 4) % 4;
}
}
wmarker_info[cid].dir = cdir;
}
}
for( i = 0; i < wmarker_num; i++ ) {
/*
printf("cf = %g\n", wmarker_info[i].cf);
*/
if( wmarker_info[i].cf < 0.5 ) wmarker_info[i].id = -1;
}
/*------------------------------------------------------------*/
for( i = j = 0; i < prev_num; i++ ) {
prev_info[i].count++;
if( prev_info[i].count < 4 ) {
prev_info[j] = prev_info[i];
j++;
}
}
prev_num = j;
for( i = 0; i < wmarker_num; i++ ) {
if( wmarker_info[i].id < 0 ) continue;
for( j = 0; j < prev_num; j++ ) {
if( prev_info[j].marker.id == wmarker_info[i].id ) break;
}
prev_info[j].marker = wmarker_info[i];
prev_info[j].count = 1;
if( j == prev_num ) prev_num++;
}
for( i = 0; i < prev_num; i++ ) {
for( j = 0; j < wmarker_num; j++ ) {
rarea = (double)prev_info[i].marker.area / (double)wmarker_info[j].area;
if( rarea < 0.7 || rarea > 1.43 ) continue;
rlen = ( (wmarker_info[j].pos[0] - prev_info[i].marker.pos[0])
* (wmarker_info[j].pos[0] - prev_info[i].marker.pos[0])
+ (wmarker_info[j].pos[1] - prev_info[i].marker.pos[1])
* (wmarker_info[j].pos[1] - prev_info[i].marker.pos[1]) ) / wmarker_info[j].area;
if( rlen < 0.5 ) break;
}
if( j == wmarker_num ) {
wmarker_info[wmarker_num] = prev_info[i].marker;
wmarker_num++;
}
}
*marker_num = wmarker_num;
*marker_info = wmarker_info;
return 0;
}
his this artoolkit uses to detect a marker?
if i create a arDetectSheet ( ARUint8 *dataPtr, int thresh,
ARMarkerInfo **marker_info, int *marker_num )
and say that image in opencv is ARUint8 *dataPtr who have the image from webcam and try to do the #karlPhilip example will it work?
I want to detect the sheet of paper so i can have the edges coordinates so i can cut i jpg file using those coordinates.
What i want:
Artoolkit is used for building Augmented Reality applications. It can't do what you described unless the piece of paper has something printed in it.
If you are considering some other framework to do this task, I suggest you invest in OpenCV.
Following matrix is given
10001
10100
00000
00000
00111
00100
00100
With one click, the pixel fill tool turns each black pixel into a white one until there isn't a black pixel that can be reached from the previous pixel. A pixel is connected with another one in up to eight ways: north, south, east, west and the four diagonals.
Puzzle link is http://www.gild.com/challenges/details/295#
This is how I solved it. Anybody can tell me which algorithm category this problems falls into.
#include <stdio.h>
#include <vector>
#include <fstream>
#include <sstream>
#include <iostream>
#include <deque>
typedef std::vector<std::vector<bool> > table_t;
class Solver {
public:
Solver(int H, int W): _height(H),
_width(W),
T(H, std::vector<bool>(W)),
num_of_clicks(0){
}
~Solver() {
}
void ReadFile(std::ifstream &ifs){
int row = 0, col = 0;
std::string file_line;
while( ifs.good() ) {
std::getline(ifs,file_line);
for ( std::string::const_iterator it = file_line.begin(); it != file_line.end(); ++it) {
if ( *it - '0' == 1 ) {
T[row][col++] = true;
} else {
T[row][col++] = false;
}
}
col = 0;
row++;
}
ifs.close();
}
void solve() {
for ( int row = 0; row < _height; ++row) {
for ( int col = 0; col < _width; ++col) {
if ( T[row][col] == true )
continue;
neighbours.clear();
num_of_clicks++;
neighbours.push_back(std::make_pair(row,col));
while ( !neighbours.empty()) {
std::pair<int,int> elem = neighbours.front();
neighbours.pop_front();
int R = elem.first;
int C = elem.second;
west (R, C);
east (R, C);
north (R, C);
south (R, C);
north_west (R, C);
south_west (R, C);
south_east (R, C);
north_east (R, C);
}
} // colum loop ends here
} // row loop ends here
std::cout << num_of_clicks << std::endl;
}
private:
int _height;
int _width;
table_t T;
std::deque<std::pair<int,int> > neighbours;
int num_of_clicks;
void west(int row, int col) {
if ( col - 1 >= 0 && T[row][col - 1 ] == false ) {
T[row][col - 1 ] = true;
neighbours.push_back(std::make_pair(row, col - 1));
}
}
void east(int row, int col) {
if ( col + 1 < _width && T[row][col + 1 ] == false ) {
T[row][col + 1 ] = true;
neighbours.push_back(std::make_pair(row, col + 1));
}
}
void north(int row, int col) {
if ( row - 1 >= 0 && T[row - 1][col] == false ) {
T[row - 1][col] = true;
neighbours.push_back(std::make_pair(row - 1, col));
}
}
void south(int row, int col) {
if ( row + 1 < _height && T[row + 1][col] == false ) {
T[row + 1][col]= true;
neighbours.push_back(std::make_pair(row + 1, col ));
}
}
void north_west(int row, int col) {
if (row - 1 >= 0 && col - 1 >= 0 &&
T[row - 1][col - 1] == false ) {
T[row - 1][col - 1] = true;
neighbours.push_back(std::make_pair(row - 1, col - 1));
}
}
void south_west(int row, int col) {
if ( row + 1 < _height && col - 1 >= 0 &&
T[row + 1][ col - 1] == false) {
T[row + 1][ col - 1] = true;
neighbours.push_back(std::make_pair(row + 1, col - 1));
}
}
void south_east(int row, int col) {
if ( row + 1 < _height && col + 1 < _width &&
T[row + 1][col + 1] == false ){
T[row + 1][col + 1] = true;
neighbours.push_back(std::make_pair(row + 1, col + 1));
}
}
void north_east(int row, int col) {
if ( row - 1 >= 0 && col + 1 < _width &&
T[row - 1][col + 1] == false ) {
T[row - 1][col + 1] = true;
neighbours.push_back(std::make_pair(row - 1, col + 1 ));
}
}
};
int main ( int argc, char **argv) {
int H = 0;
int W = 0;
std::ifstream input(argv[1]);
if ( input.peek() == EOF ) {
return 1;
}
// Read the first line.
std::string file_line;
std::getline(input,file_line);
std::istringstream iss;
iss.clear();
iss.str(file_line);
// Get the height and width of the image.
iss >> H >> W;
Solver s(H,W);
s.ReadFile(input);
s.solve();
return 0;
}
This flood fill operation is a classic application of morphological reconstruction by dilation (with the marker image being black with a single white start pixel and the mask image being the inverse of the original image). Compare L. Vincents paper on an efficient implementation, which looks much like your implementation, and the excellent introductory talk by O. Eidheim.
Its Called Connected Component Labeling. Note its the generalized version of it, Here's the Wikipedia entry