|
|
/* File: sv_h263_morph.c */ /*****************************************************************************
** Copyright (c) Digital Equipment Corporation, 1995, 1997 ** ** ** ** All Rights Reserved. Unpublished rights reserved under the copyright ** ** laws of the United States. ** ** ** ** The software contained on this media is proprietary to and embodies ** ** the confidential technology of Digital Equipment Corporation. ** ** Possession, use, duplication or dissemination of the software and ** ** media is authorized only pursuant to a valid written license from ** ** Digital Equipment Corporation. ** ** ** ** RESTRICTED RIGHTS LEGEND Use, duplication, or disclosure by the U.S. ** ** Government is subject to restrictions as set forth in Subparagraph ** ** (c)(1)(ii) of DFARS 252.227-7013, or in FAR 52.227-19, as applicable. ** ******************************************************************************/ /*
#define _SLIBDEBUG_
*/
#include "sv_h263.h"
#include "proto.h"
#ifdef _SLIBDEBUG_
#include "sc_debug.h"
#define _DEBUG_ 0 /* detailed debuging statements */
#define _VERBOSE_ 1 /* show progress */
#define _VERIFY_ 0 /* verify correct operation */
#define _WARN_ 1 /* warnings about strange behavior */
#endif
static unsigned char min5(unsigned char a, unsigned char b, unsigned char c, unsigned char d, unsigned char e) ; static unsigned char max5(unsigned char a, unsigned char b, unsigned char c, unsigned char d, unsigned char e) ; static void ErodeX(unsigned char *image, unsigned char *out, int rows, int cols); static void DilateX(unsigned char *image, unsigned char *out, int rows, int cols); static void ErodeS(unsigned char *image, unsigned char *out, int rows, int cols, int sr, int sc); static void DilateS(unsigned char *image, unsigned char *out, int rows, int cols, int sr, int sc); static void Dilate(unsigned char *image, unsigned char *out, int rows, int cols, int sr, int sc); static void Erode(unsigned char *image, unsigned char *out, int rows, int cols, int sr, int sc); static void Open(unsigned char *image, unsigned char *out, int rows, int cols, int sr, int sc);
static void EdgeSelect(H263_PictImage *input, H263_PictImage *filtd, unsigned char *edge, H263_PictImage *output, int rows, int cols) ;
/*****************************************************************************************************
* Function min5 * Computes the min of the five elements ****************************************************************************************************/ static unsigned char min5(unsigned char a, unsigned char b, unsigned char c, unsigned char d, unsigned char e) { unsigned char out;
out = a; if(b<out) out=b; if(c<out) out=c; if(d<out) out=d; if(e<out) out=e; return out; }
/*****************************************************************************************************
* Function max5 * Computes the max of the five elements ****************************************************************************************************/ static unsigned char max5(unsigned char a, unsigned char b, unsigned char c, unsigned char d, unsigned char e) { unsigned char out;
out = a; if(b>out) out=b; if(c>out) out=c; if(d>out) out=d; if(e>out) out=e; return out; }
/*****************************************************************************************************
* Function: ErodeX * Erosion of image (dimensions rows, cols) by a "+" structuring element ****************************************************************************************************/ static void ErodeX(unsigned char *image, unsigned char *out, int rows, int cols) { int i, j; unsigned char *pi, *po;
pi = image; po = out;
/**** First line ****/ /* First pixel */ *po = min5(*pi, *pi, *(pi+1), *pi, *(pi+cols)); pi++; po++; /* Center pixels */ for(j=1; j<cols-1; j++, pi++, po++) { *po = min5(*(pi-1), *pi, *(pi+1), *pi, *(pi+cols)); } /* Last pixel */ *po = min5(*(pi-1), *pi, *pi, *pi, *(pi+cols)); pi++; po++;
/**** Center lines ****/ for(i=1; i<rows-1; i++) { /* First pixel */ *po = min5(*pi, *pi, *(pi+1), *(pi-cols), *(pi+cols)); pi++; po++; /* Center pixels */ for(j=1; j<cols-1; j++, pi++, po++) { *po = min5(*(pi-1), *pi, *(pi+1), *(pi-cols), *(pi+cols)); } /* Last pixel */ *po = min5(*(pi-1), *pi, *pi, *(pi-cols), *(pi+cols)); pi++; po++; }
/**** Last line ****/ /* First pixel */ *po = min5(*pi, *pi, *(pi+1), *(pi-cols), *pi); pi++; po++; /* Center pixels */ for(j=1; j<cols-1; j++, pi++, po++) { *po = min5(*(pi-1), *pi, *(pi+1), *(pi-cols), *pi); } /* Last pixel */ *po = min5(*(pi-1), *pi, *pi, *(pi-cols), *pi); pi++; po++; }
/*****************************************************************************************************
* Function: ErodeX * Erosion of image (dimensions rows, cols) by a "+" structuring element ****************************************************************************************************/ static void DilateX(unsigned char *image, unsigned char *out, int rows, int cols) { int i, j; unsigned char *pi, *po;
pi = image; po = out;
/**** First line ****/ /* First pixel */ *po = max5(*pi, *pi, *(pi+1), *pi, *(pi+cols)); pi++; po++; /* Center pixels */ for(j=1; j<cols-1; j++, pi++, po++) { *po = max5(*(pi-1), *pi, *(pi+1), *pi, *(pi+cols)); } /* Last pixel */ *po = max5(*(pi-1), *pi, *pi, *pi, *(pi+cols)); pi++; po++;
/**** Center lines ****/ for(i=1; i<rows-1; i++) { /* First pixel */ *po = max5(*pi, *pi, *(pi+1), *(pi-cols), *(pi+cols)); pi++; po++; /* Center pixels */ for(j=1; j<cols-1; j++, pi++, po++) { *po = max5(*(pi-1), *pi, *(pi+1), *(pi-cols), *(pi+cols)); } /* Last pixel */ *po = max5(*(pi-1), *pi, *pi, *(pi-cols), *(pi+cols)); pi++; po++; }
/**** Last line ****/ /* First pixel */ *po = max5(*pi, *pi, *(pi+1), *(pi-cols), *pi); pi++; po++; /* Center pixels */ for(j=1; j<cols-1; j++, pi++, po++) { *po = max5(*(pi-1), *pi, *(pi+1), *(pi-cols), *pi); } /* Last pixel */ *po = max5(*(pi-1), *pi, *pi, *(pi-cols), *pi); pi++; po++; }
/*****************************************************************************************************
* Function: ErodeS * Erosion of image (dimensions rows, cols) by a square structuring element of dimensions (sr, sc) ****************************************************************************************************/ static void ErodeS(unsigned char *image, unsigned char *out, int rows, int cols, int sr, int sc) { int i, j, k, l, du, db, dl, dr, sr2, sc2; unsigned char *pi, *po, *pse, min, odd;
odd = 1; if (!(sr%2) || !(sc%2)) odd = 0;
sr2 = sr >> 1; sc2 = sc >> 1;
pi = image; po = out; for(i=0; i<rows; i++) { for(j=0; j<cols; j++, pi++, po++) {
du = i>sr2 ? sr2 : i; dl = j > sc2 ? sc2 : j;
if(odd) { db = (rows-1-i) > sr2 ? sr2 : (rows-1-i); dr = (cols-1-j) > sc2 ? sc2 : (cols-1-j); } else { db = (rows-1-i) > sr2-1 ? sr2-1 : (rows-1-i); dr = (cols-1-j) > sc2-1 ? sc2-1 : (cols-1-j); }
min = 255; for(k=-du; k<=db; k++) { pse = pi + k * cols - dl; for(l=-dl; l<=dr; l++, pse++) { min = *pse < min ? *pse : min; } } *po = min; } } }
/*****************************************************************************************************
* Function: DilateS * Dilation of image (dimensions rows, cols) by a square structuring element of dimensions (sr, sc) ****************************************************************************************************/ static void DilateS(unsigned char *image, unsigned char *out, int rows, int cols, int sr, int sc) { int i, j, k, l, du, db, dl, dr, sr2, sc2; unsigned char *pi, *po, *pse, max, odd;
odd = 1; if (!(sr%2) || !(sc%2)) odd = 0;
sr2 = sr >> 1; sc2 = sc >> 1;
pi = image; po = out; for(i=0; i<rows; i++) { for(j=0; j<cols; j++, pi++, po++) {
du = i>sr2 ? sr2 : i; dl = j > sc2 ? sc2 : j;
if(odd) { db = (rows-1-i) > sr2 ? sr2 : (rows-1-i); dr = (cols-1-j) > sc2 ? sc2 : (cols-1-j); } else { db = (rows-1-i) > sr2-1 ? sr2-1 : (rows-1-i); dr = (cols-1-j) > sc2-1 ? sc2-1 : (cols-1-j); }
max = 0; for(k=-du; k<=db; k++) { for(l=-dl; l<=dr; l++, pse++) { pse = pi + k * cols + l; max = (*pse > max) ? *pse : max; } } *po = max; } } }
/*****************************************************************************************************
* Function: Dilate * Dilation of image (dimensions rows, cols) by a structuring element of dimensions (sr, sc). * If (sr, sc) are positive the structuring element is positive. If they are -1 it is * the cross '+' ****************************************************************************************************/ static void Dilate(unsigned char *image, unsigned char *out, int rows, int cols, int sr, int sc) { if(sr > 0 && sc > 0) { DilateS(image, out, rows, cols, sr, sc); } else if(sr==-1 && sc ==-1) { DilateX(image, out, rows, cols); } else { _SlibDebug(_WARN_, printf("Dilate() Unknown structuring element\n") ); return; } }
/*****************************************************************************************************
* Function: Erode * Erosion of image (dimensions rows, cols) by a structuring element of dimensions (sr, sc). * If (sr, sc) are positive the structuring element is positive. If they are -1 it is * the cross '+' ****************************************************************************************************/ static void Erode(unsigned char *image, unsigned char *out, int rows, int cols, int sr, int sc) { if(sr > 0 && sc > 0) { ErodeS(image, out, rows, cols, sr, sc); } else if(sr==-1 && sc ==-1) { ErodeX(image, out, rows, cols); } else { _SlibDebug(_WARN_, printf("Erode() Unknown structuring element\n") ); return; } }
/*****************************************************************************************************
* Function: Open * Opening of image (dimensions rows, cols) by a square structuring element of dimensions (sr, sc) ****************************************************************************************************/ static void Open(unsigned char *image, unsigned char *out, int rows, int cols, int sr, int sc) { unsigned char *tmp;
if (!(tmp = (unsigned char *)ScAlloc(rows*cols))) { _SlibDebug(_WARN_, printf("Open() ScAlloc failed\n") ); return; } Erode(image, tmp, rows, cols, sr, sc); Dilate(tmp, out, rows, cols, sr, sc); ScFree(tmp); }
/*****************************************************************************************************
* Function: Close * Closing of image (dimensions rows, cols) by a square structuring element of dimensions (sr, sc) ****************************************************************************************************/ void Close(unsigned char *image, unsigned char *out, int rows, int cols, int sr, int sc) { unsigned char *tmp;
if (!(tmp = (unsigned char *)ScAlloc(rows*cols))) { _SlibDebug(_WARN_, printf("Close() ScAlloc failed\n") ); return; } Dilate(image, tmp, rows, cols, sr, sc); Erode(tmp, out, rows, cols, sr, sc); ScFree(tmp); }
/*****************************************************************************************************
* Function: OpenClose * Open/Closing of image (dimensions rows, cols) by a square structuring element of dimensions (sr, sc) ****************************************************************************************************/ void OpenClose(unsigned char *image, unsigned char *out, int rows, int cols, int sr, int sc) { unsigned char *tmp;
if (!(tmp = (unsigned char *)ScAlloc(rows*cols))) { _SlibDebug(_WARN_, printf("OpenClose() ScAlloc failed\n") ); return; } Open(image, tmp, rows, cols, sr, sc); Close(tmp, out, rows, cols, sr, sc); ScFree(tmp); }
/*****************************************************************************************************
* Function: CloseOpen * Open/Closing of image (dimensions rows, cols) by a square structuring element of dimensions (sr, sc) ****************************************************************************************************/ void CloseOpen(unsigned char *image, unsigned char *out, int rows, int cols, int sr, int sc) { unsigned char *tmp;
if (!(tmp = (unsigned char *)ScAlloc(rows*cols))) { _SlibDebug(_WARN_, printf("CloseOpen() ScAlloc failed\n") ); return; } Close(image, tmp, rows, cols, sr, sc); Open(tmp, out, rows, cols, sr, sc); ScFree(tmp); }
/*****************************************************************************************************
* Function: GeoDilate * Geodesic dilation of size one of image with respect to reference ****************************************************************************************************/ void GeoDilate(unsigned char *image, unsigned char *reference, int rows, int cols, int sr, int sc) { int i, j; unsigned char *pi, *pr, *pt, *tmp;
if (!(tmp = (unsigned char *)ScAlloc(rows*cols))) { _SlibDebug(_WARN_, printf("GeoDilate() ScAlloc failed\n") ); return; } Dilate(image, tmp, rows, cols, sr, sc);
pi = image; pr = reference; pt = tmp; for(i=0; i<rows; i++) { for(j=0; j<cols; j++, pi++, pr++, pt++) { *pi = *pr < *pt ? *pr : *pt; } } ScFree(tmp); }
/*****************************************************************************************************
* Function: GeoErode * Geodesic erosion of size one of image with respect to reference ****************************************************************************************************/ void GeoErode(unsigned char *image, unsigned char *reference, int rows, int cols, int sr, int sc) { int i, j; unsigned char *pi, *pr, *pt, *tmp;
if (!(tmp = (unsigned char *)ScAlloc(rows*cols))) { _SlibDebug(_WARN_, printf("GeoErode() ScAlloc failed\n") ); return; } Erode(image, tmp, rows, cols, sr, sc);
pi = image; pr = reference; pt = tmp; for(i=0; i<rows; i++) { for(j=0; j<cols; j++, pi++, pr++, pt++) { *pi = (-(*pr) < (-*pt)) ? *pr : *pt; } } ScFree(tmp); }
/****************************************************************************************************
* Function: RecDilate * Reconstruction by dilation of image with respect to reference using a structural element of * dimenions (sr, sc). ****************************************************************************************************/ void RecDilate(unsigned char *image, unsigned char *reference, int rows, int cols, int sr, int sc) { int i, sz; unsigned char *prevImg, *pi, *Pi, differ;
sz = rows * cols; if (!(prevImg = (unsigned char *)ScAlloc(sz))) { _SlibDebug(_WARN_, printf("RecDilate() ScAlloc failed\n") ); return; } do { memcpy(prevImg, image, rows*cols); GeoDilate(image, reference, rows, cols, sr, sc); pi = image; Pi = prevImg; differ = 0; for(i=0; i<sz; i++) if(*(pi++) != *(Pi++)) { differ = 1; break;} } while (differ); ScFree(prevImg); }
/****************************************************************************************************
* Function: RecErode * Reconstruction by erosion of image with respect to reference using a structural element of * dimenions (sr, sc). ****************************************************************************************************/ void RecErode(unsigned char *image, unsigned char *reference, int rows, int cols, int sr, int sc) { int i, sz; unsigned char *prevImg, *pi, *Pi, differ;
sz = rows * cols; if (!(prevImg = (unsigned char *)ScAlloc(sz))) { _SlibDebug(_WARN_, printf("RecErode() ScAlloc failed\n") ); return; } do { memcpy(prevImg, image, rows*cols); GeoErode(image, reference, rows, cols, sr, sc); pi = image; Pi = prevImg; differ = 0; for(i=0; i<sz; i++) if(*(pi++) != *(Pi++)) { differ = 1; break;} } while (differ); ScFree(prevImg); }
/****************************************************************************************************
* Function: OpenRecErode * Open by reconstruction of erosion of image using a structural element of * dimenions (sr, sc). ****************************************************************************************************/ void OpenRecErode(unsigned char *image, unsigned char *out, int rows, int cols, int sr, int sc) { int sz;
sz = rows * cols; Erode(image, out, rows, cols, sr, sc); RecDilate(out, image, rows, cols, sr, sc); }
/****************************************************************************************************
* Function: CloseRecDilate * Closing by reconstruction of dilation of image using a structural element of * dimenions (sr, sc). ****************************************************************************************************/ void CloseRecDilate(unsigned char *image, unsigned char *out, int rows, int cols, int sr, int sc) { int sz;
sz = rows * cols; Dilate(image, out, rows, cols, sr, sc); RecErode(out, image, rows, cols, sr, sc); }
/****************************************************************************************************
* Function: OpenCloseRec * Open-closing by reconstruction of image using a structural element of * dimenions (sr, sc). ****************************************************************************************************/ void OpenCloseRec(unsigned char *image, unsigned char *out, int rows, int cols, int sr, int sc) { int sz; unsigned char *opened;
sz = rows * cols; if (!(opened = (unsigned char *)ScAlloc(sz))) { _SlibDebug(_WARN_, printf("OpenCloseRec() ScAlloc failed\n") ); return; } OpenRecErode(image, opened, rows, cols, sr, sc); CloseRecDilate(opened, out, rows, cols, sr, sc); ScFree(opened); }
/****************************************************************************************************
* Function: PredOpenCloseRec * Open-closing by reconstruction of image using a structural element of * dimenions (sr, sc), for prediction images. ****************************************************************************************************/ void PredOpenCloseRec(int *predimage, int *predout, int rows, int cols, int sr, int sc) { int sz, i; unsigned char *opened, *image, *out;
sz = rows * cols; if (!(image = (unsigned char *)ScAlloc(sz))) { _SlibDebug(_WARN_, printf("PredOpenCloseRec() ScAlloc failed\n") ); return; } if (!(out = (unsigned char *)ScAlloc(sz))) { _SlibDebug(_WARN_, printf("PredOpenCloseRec() ScAlloc failed\n") ); return; } for(i=0; i<sz; i++) image[i] = (unsigned char) predimage[i] + 128;
if (!(opened = (unsigned char *)ScAlloc(sz))) { _SlibDebug(_WARN_, printf("PredOpenCloseRec() ScAlloc failed\n") ); return; } OpenRecErode(image, opened, rows, cols, sr, sc); CloseRecDilate(opened, out, rows, cols, sr, sc);
for(i=0; i<sz; i++) predout[i] = (int) out[i] - 128;
ScFree(opened); ScFree(image); ScFree(out); }
/**************************************************************************************************
* Function: EdgeSelect * Given the edge map, copies to the output: pixels from the input image if edge points, * pixels form the filtered image if not edge points. *************************************************************************************************/ static void EdgeSelect(H263_PictImage *input, H263_PictImage *filtd, unsigned char *edge, H263_PictImage *output, int rows, int cols) { unsigned char *pi, *po, *pf, *pe; int i, j;
/* Luminance */ pi = input->lum; pf = filtd->lum; po = output->lum; pe = edge; for(i=0; i<rows; i++) { for(j=0; j<cols; j++, pi++, pf++, pe++, po++) { *po = (*pe ? *pi : *pf); } }
rows /=2; cols /=2;
/* Color 1 */ pi = input->Cr; pf = filtd->Cr; po = output->Cr; pe = edge; for(i=0; i<rows; i++) { for(j=0; j<cols; j++, pi++, pf++, pe+=2, po++) { *po = (*pe ? *pi : *pf); } pe += cols; }
/* Color 2 */ pi = input->Cb; pf = filtd->Cb; po = output->Cb; pe = edge; for(i=0; i<rows; i++) { for(j=0; j<cols; j++, pi++, pf++, pe+=2, po++) { *po = (*pe ? *pi : *pf); } pe += cols; } }
/**************************************************************************************************
* Function: AdaptClean * Adaptly cleans curr_image, by filtering it by open/close by reconstruction at the pixels * where there is no edge info. The edge map is grown by the size of the morphological * operator, to avoid oversmoothing of details. sr, sc are the dimensions of the structuring * element for the morphologic operations *************************************************************************************************/ H263_PictImage *sv_H263AdaptClean(SvH263CompressInfo_t *H263Info, H263_PictImage *curr_image, int rows, int cols, int sr, int sc) { H263_PictImage *morph, *clean; unsigned char *Edge, *Orient, *CleanEmap;
if (!(Edge = (unsigned char *)ScAlloc(rows*cols))) { _SlibDebug(_WARN_, printf("PredOpenCloseRec() ScAlloc failed\n") ); return(NULL); } if (!(Orient = (unsigned char *)ScAlloc(rows*cols))) { _SlibDebug(_WARN_, printf("PredOpenCloseRec() ScAlloc failed\n") ); return(NULL); } sv_H263EdgeMap(curr_image->lum, Edge, Orient, rows, cols); morph = sv_H263InitImage(H263Info->pels*H263Info->lines);
OpenCloseRec(H263Info->curr_image->lum, morph->lum, rows, cols, sr, sc); OpenCloseRec(H263Info->curr_image->Cr, morph->Cr, rows >> 1, cols >> 1, sr, sc); OpenCloseRec(H263Info->curr_image->Cb, morph->Cb, rows >> 1, cols >> 1, sr, sc);
clean = sv_H263InitImage(rows*cols);
if (!(CleanEmap = (unsigned char *)ScAlloc(rows*cols))) { _SlibDebug(_WARN_, printf("PredOpenCloseRec() ScAlloc failed\n") ); return(NULL); }
CloseOpen(Edge, CleanEmap, rows, cols, sr, sc); EdgeSelect(H263Info->curr_image, morph, CleanEmap, clean, rows, cols);
sv_H263FreeImage(morph); ScFree(CleanEmap); ScFree(Orient); ScFree(Edge);
return clean; }
/*****************************************************************
* Function MorphLayers * Builds an array of successively more morphologically low pass * filtered images. sz is the size of the structuring element (-1 for * the cross '+'). *****************************************************************/ H263_PictImage **sv_H263MorphLayers(H263_PictImage *img, int depth, int rows, int cols, int sz) { int d; H263_PictImage **PictFiltd;
PictFiltd = (H263_PictImage **) ScAlloc(depth*sizeof(H263_PictImage *)); for(d=0; d<depth; d++) { PictFiltd[d] = sv_H263InitImage(rows*cols); }
/* Luminance */ memcpy(PictFiltd[0]->lum, img->lum, rows*cols); for(d=1; d<depth; d++) OpenCloseRec(PictFiltd[d-1]->lum, PictFiltd[d]->lum, rows, cols, sz, sz);
rows/=2; cols/=2;
/* Chroma 1 */ memcpy(PictFiltd[0]->Cr, img->Cr, rows*cols); for(d=1; d<depth; d++) OpenCloseRec(PictFiltd[d-1]->Cr, PictFiltd[d]->Cr, rows, cols, sz, sz);
/* Chroma 2 */ memcpy(PictFiltd[0]->Cb, img->Cb, rows*cols); for(d=1; d<depth; d++) OpenCloseRec(PictFiltd[d-1]->Cb, PictFiltd[d]->Cb, rows, cols, sz, sz);
return PictFiltd; }
|