| | |
| | | #include "image.h" |
| | | #include "utils.h" |
| | | #include <stdio.h> |
| | | |
| | | int windows = 0; |
| | |
| | | for(i = 0; i < a.h*a.w*a.c; ++i) a.data[i] -= b.data[i]; |
| | | } |
| | | |
| | | void embed_image(image source, image dest, int h, int w) |
| | | { |
| | | int i,j,k; |
| | | for(k = 0; k < source.c; ++k){ |
| | | for(i = 0; i < source.h; ++i){ |
| | | for(j = 0; j < source.w; ++j){ |
| | | double val = get_pixel(source, i,j,k); |
| | | set_pixel(dest, h+i, w+j, k, val); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | image collapse_image_layers(image source, int border) |
| | | { |
| | | int h = source.h; |
| | | h = (h+border)*source.c - border; |
| | | image dest = make_image(h, source.w, 1); |
| | | int i; |
| | | for(i = 0; i < source.c; ++i){ |
| | | image layer = get_image_layer(source, i); |
| | | int h_offset = i*(source.h+border); |
| | | embed_image(layer, dest, h_offset, 0); |
| | | free_image(layer); |
| | | } |
| | | return dest; |
| | | } |
| | | |
| | | void z_normalize_image(image p) |
| | | { |
| | | normalize_array(p.data, p.h*p.w*p.c); |
| | | } |
| | | |
| | | void normalize_image(image p) |
| | | { |
| | | double *min = calloc(p.c, sizeof(double)); |
| | |
| | | } |
| | | } |
| | | for(i = 0; i < p.c; ++i){ |
| | | if(max[i] - min[i] < .00001){ |
| | | if(max[i] - min[i] < .000000001){ |
| | | min[i] = 0; |
| | | max[i] = 1; |
| | | } |
| | |
| | | normalize_image(copy); |
| | | |
| | | char buff[256]; |
| | | sprintf(buff, "%s (%d)", name, windows); |
| | | //sprintf(buff, "%s (%d)", name, windows); |
| | | sprintf(buff, "%s", name); |
| | | |
| | | IplImage *disp = cvCreateImage(cvSize(p.w,p.h), IPL_DEPTH_8U, p.c); |
| | | int step = disp->widthStep; |
| | | cvNamedWindow(buff, CV_WINDOW_AUTOSIZE); |
| | | cvMoveWindow(buff, 100*(windows%10) + 200*(windows/10), 100*(windows%10)); |
| | | //cvMoveWindow(buff, 100*(windows%10) + 200*(windows/10), 100*(windows%10)); |
| | | ++windows; |
| | | for(i = 0; i < p.h; ++i){ |
| | | for(j = 0; j < p.w; ++j){ |
| | |
| | | } |
| | | } |
| | | } |
| | | if(disp->height < 100 || disp->width < 100){ |
| | | free_image(copy); |
| | | if(disp->height < 500 || disp->width < 500){ |
| | | int w = 1500; |
| | | int h = w*p.h/p.w; |
| | | if(h > 1000){ |
| | | h = 1000; |
| | | w = h*p.w/p.h; |
| | | } |
| | | IplImage *buffer = disp; |
| | | disp = cvCreateImage(cvSize(100,100*p.h/p.w), buffer->depth, buffer->nChannels); |
| | | disp = cvCreateImage(cvSize(w, h), buffer->depth, buffer->nChannels); |
| | | cvResize(buffer, disp, CV_INTER_NN); |
| | | cvReleaseImage(&buffer); |
| | | } |
| | |
| | | } |
| | | } |
| | | |
| | | void show_image_collapsed(image p, char *name) |
| | | { |
| | | image c = collapse_image_layers(p, 1); |
| | | show_image(c, name); |
| | | free_image(c); |
| | | } |
| | | |
| | | image make_empty_image(int h, int w, int c) |
| | | { |
| | | image out; |
| | |
| | | image out = make_image(h,w,c); |
| | | int i; |
| | | for(i = 0; i < h*w*c; ++i){ |
| | | out.data[i] = (.5-(double)rand()/RAND_MAX); |
| | | out.data[i] = rand_normal(); |
| | | } |
| | | return out; |
| | | } |
| | | |
| | | image make_random_kernel(int size, int c) |
| | | void add_scalar_image(image m, double s) |
| | | { |
| | | int i; |
| | | for(i = 0; i < m.h*m.w*m.c; ++i) m.data[i] += s; |
| | | } |
| | | |
| | | void scale_image(image m, double s) |
| | | { |
| | | int i; |
| | | for(i = 0; i < m.h*m.w*m.c; ++i) m.data[i] *= s; |
| | | } |
| | | |
| | | image make_random_kernel(int size, int c, double scale) |
| | | { |
| | | int pad; |
| | | if((pad=(size%2==0))) ++size; |
| | | image out = make_random_image(size,size,c); |
| | | scale_image(out, scale); |
| | | int i,k; |
| | | if(pad){ |
| | | for(k = 0; k < out.c; ++k){ |
| | |
| | | add_pixel(m, x, y, c, val); |
| | | } |
| | | |
| | | void two_d_convolve(image m, int mc, image kernel, int kc, int stride, image out, int oc) |
| | | void two_d_convolve(image m, int mc, image kernel, int kc, int stride, image out, int oc, int edge) |
| | | { |
| | | int x,y,i,j; |
| | | for(x = 0; x < m.h; x += stride){ |
| | | for(y = 0; y < m.w; y += stride){ |
| | | int xstart, xend, ystart, yend; |
| | | if(edge){ |
| | | xstart = ystart = 0; |
| | | xend = m.h; |
| | | yend = m.w; |
| | | }else{ |
| | | xstart = kernel.h/2; |
| | | ystart = kernel.w/2; |
| | | xend = m.h-kernel.h/2; |
| | | yend = m.w - kernel.w/2; |
| | | } |
| | | for(x = xstart; x < xend; x += stride){ |
| | | for(y = ystart; y < yend; y += stride){ |
| | | double sum = 0; |
| | | for(i = 0; i < kernel.h; ++i){ |
| | | for(j = 0; j < kernel.w; ++j){ |
| | | sum += get_pixel(kernel, i, j, kc)*get_pixel_extend(m, x+i-kernel.h/2, y+j-kernel.w/2, mc); |
| | | } |
| | | } |
| | | add_pixel(out, x/stride, y/stride, oc, sum); |
| | | add_pixel(out, (x-xstart)/stride, (y-ystart)/stride, oc, sum); |
| | | } |
| | | } |
| | | } |
| | |
| | | return sum; |
| | | } |
| | | |
| | | void convolve(image m, image kernel, int stride, int channel, image out) |
| | | void convolve(image m, image kernel, int stride, int channel, image out, int edge) |
| | | { |
| | | assert(m.c == kernel.c); |
| | | int i; |
| | | zero_channel(out, channel); |
| | | for(i = 0; i < m.c; ++i){ |
| | | two_d_convolve(m, i, kernel, i, stride, out, channel); |
| | | two_d_convolve(m, i, kernel, i, stride, out, channel, edge); |
| | | } |
| | | /* |
| | | int j; |
| | |
| | | } |
| | | } |
| | | |
| | | void kernel_update(image m, image update, int stride, int channel, image out) |
| | | void kernel_update(image m, image update, int stride, int channel, image out, int edge) |
| | | { |
| | | assert(m.c == update.c); |
| | | zero_image(update); |
| | | int i, j; |
| | | for(i = 0; i < m.h; i += stride){ |
| | | for(j = 0; j < m.w; j += stride){ |
| | | double error = get_pixel(out, i/stride, j/stride, channel); |
| | | int i, j, istart, jstart, iend, jend; |
| | | if(edge){ |
| | | istart = jstart = 0; |
| | | iend = m.h; |
| | | jend = m.w; |
| | | }else{ |
| | | istart = update.h/2; |
| | | jstart = update.w/2; |
| | | iend = m.h-update.h/2; |
| | | jend = m.w - update.w/2; |
| | | } |
| | | for(i = istart; i < iend; i += stride){ |
| | | for(j = jstart; j < jend; j += stride){ |
| | | double error = get_pixel(out, (i-istart)/stride, (j-jstart)/stride, channel); |
| | | single_update(m, update, i, j, error); |
| | | } |
| | | } |
| | | /* |
| | | for(i = 0; i < update.h*update.w*update.c; ++i){ |
| | | update.data[i] /= (m.h/stride)*(m.w/stride); |
| | | } |
| | | */ |
| | | } |
| | | |
| | | void single_back_convolve(image m, image kernel, int x, int y, double val) |
| | |
| | | } |
| | | } |
| | | |
| | | void back_convolve(image m, image kernel, int stride, int channel, image out) |
| | | void back_convolve(image m, image kernel, int stride, int channel, image out, int edge) |
| | | { |
| | | assert(m.c == kernel.c); |
| | | int i, j; |
| | | for(i = 0; i < m.h; i += stride){ |
| | | for(j = 0; j < m.w; j += stride){ |
| | | double val = get_pixel(out, i/stride, j/stride, channel); |
| | | int i, j, istart, jstart, iend, jend; |
| | | if(edge){ |
| | | istart = jstart = 0; |
| | | iend = m.h; |
| | | jend = m.w; |
| | | }else{ |
| | | istart = kernel.h/2; |
| | | jstart = kernel.w/2; |
| | | iend = m.h-kernel.h/2; |
| | | jend = m.w - kernel.w/2; |
| | | } |
| | | for(i = istart; i < iend; i += stride){ |
| | | for(j = jstart; j < jend; j += stride){ |
| | | double val = get_pixel(out, (i-istart)/stride, (j-jstart)/stride, channel); |
| | | single_back_convolve(m, kernel, i, j, val); |
| | | } |
| | | } |
| | | } |
| | | |
| | | void print_image(image m) |
| | | { |
| | | int i; |
| | | for(i =0 ; i < m.h*m.w*m.c; ++i) printf("%lf, ", m.data[i]); |
| | | printf("\n"); |
| | | } |
| | | |
| | | void free_image(image m) |
| | | { |
| | | free(m.data); |