220 lines
6.7 KiB
C
220 lines
6.7 KiB
C
/* File: sv_h263_edge.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. **
|
|
******************************************************************************/
|
|
|
|
#include "sv_h263.h"
|
|
#include "proto.h"
|
|
|
|
#define BSIZE 8
|
|
#define BSZSHIFT 6
|
|
#define EDGE_TH 150
|
|
|
|
|
|
static void lineDetect(int H, int V, int D1, int D2, unsigned char *pe, unsigned char *po);
|
|
static void findEdge(int ul, int u, int ur, int l, int c, int r, int bl, int b, int br,
|
|
unsigned char *pe, unsigned char *po, char mode);
|
|
|
|
|
|
/***********************************************************************************
|
|
* Function: Sobel
|
|
* Sobel gradient-based edge detector (see Jain, page 349)
|
|
**********************************************************************************/
|
|
void Sobel(int ul, int u, int ur, int l, int c, int r, int bl, int b, int br,
|
|
unsigned char *pe, unsigned char *po)
|
|
{
|
|
int gx, gy, AGX, AGY;
|
|
|
|
gx = -ul + ur - (l<<1) + (r<<1) - bl + br;
|
|
gy = -ul + bl - (u<<1) + (b<<1) - ur + br;
|
|
|
|
AGX = gx > 0 ? gx : -gx;
|
|
AGY = gy > 0 ? gy : -gy;
|
|
|
|
*pe = (AGX+AGY)> EDGE_TH ? 255 : 0;
|
|
}
|
|
|
|
/***********************************************************************************
|
|
* Function: lineDetect
|
|
* Compass-based line detector (see Jain, page 357)
|
|
**********************************************************************************/
|
|
void lineDetect(int H, int V, int D1, int D2, unsigned char *pe, unsigned char *po)
|
|
{
|
|
int AH, AV, AD1, AD2, ED;
|
|
|
|
AH = (H>0 ? H : -H);
|
|
AV = (V>0 ? V : -V);
|
|
AD1 = (D1>0 ? D1: -D1);
|
|
AD2 = (D2>0 ? D2: -D2);
|
|
|
|
if(AH>=AV && AH>=AD1 && AH>=AD2) {
|
|
ED = AH;
|
|
*po = 1;
|
|
} else if (AV>=AH && AV>=AD1 && AV>=AD2) {
|
|
ED = AV;
|
|
*po = 2;
|
|
} else if (AD1>=AH && AD1>=AV && AD1>=AD2) {
|
|
ED = AD1;
|
|
*po = 3;
|
|
} else {
|
|
ED = AD2;
|
|
*po = 4;
|
|
}
|
|
|
|
if (ED < EDGE_TH) { *pe = 0; *po = 0;}
|
|
else *pe = 255;
|
|
}
|
|
|
|
/**********************************************************************************
|
|
* Function: findEdge
|
|
* Computes edge magnitude and orientation given the pixel's neighborhood
|
|
*********************************************************************************/
|
|
void findEdge(int ul, int u, int ur, int l, int c, int r, int bl, int b, int br,
|
|
unsigned char *pe, unsigned char *po, char mode)
|
|
{
|
|
switch(mode) {
|
|
case 'L':
|
|
{
|
|
int H, V, D1, D2;
|
|
|
|
/* Horizontal gradient */
|
|
H = -ul -u -ur + (l<<1) + (c<<1) + (r<<1) -bl -b -br;
|
|
/* Vertical gradient */
|
|
V = -ul + (u<<1) -ur -l + (c<<1) -r -bl + (b<<1) -br;
|
|
/* Diagonal gradient 1 */
|
|
D1 = -ul -u + (ur<<1) -l + (c<<1) -r + (bl<<1) -b -br;
|
|
/* Diagonal gradient 2*/
|
|
D2 = (ul<<1) -u -ur -l + (c<<1) -r -bl -b +(br<<1);
|
|
lineDetect(H, V, D1, D2, pe, po);
|
|
break;
|
|
}
|
|
case 'S':
|
|
{
|
|
Sobel(ul, u, ur, l, c, r, bl, b, br, pe, po);
|
|
break;
|
|
}
|
|
default:
|
|
/* printf("Unknown edge finder in findEdge...\n"); */
|
|
/* exit(0); */
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
/***********************************************************************************
|
|
* Function: EdgeMap
|
|
* Computes an edge map for image. Edge magnitude is returned in EdgeMag and
|
|
* orientation in EdgeOrient.
|
|
**********************************************************************************/
|
|
void sv_H263EdgeMap(unsigned char *image, unsigned char *EdgeMag, unsigned char *EdgeOrient,
|
|
int rows, int cols)
|
|
{
|
|
unsigned char *pi, *pe, *po;
|
|
int i, j, ul, u, ur, l, c, r, bl, b, br;
|
|
|
|
pi = image;
|
|
pe = EdgeMag;
|
|
po = EdgeOrient;
|
|
/* Clear first line */
|
|
for(j=0; j<cols; j++) {
|
|
*(pe++) = 0;
|
|
*(po++) = 0;
|
|
}
|
|
pi = image + cols;
|
|
for(i=1; i<rows-1; i++) {
|
|
/* Clear first pixel */
|
|
*(pe++) = 0; *(po++) = 0; pi++;
|
|
|
|
/* Start gathering 3x3 neighberhood */
|
|
ul = *(pi-cols-1); u = *(pi-cols);
|
|
l = *(pi-1); c = *pi;
|
|
bl = *(pi+cols-1); b = *(pi+cols);
|
|
|
|
/* Compute edge map */
|
|
for(j=1; j<cols-1; j++, pi++, pe++, po++) {
|
|
|
|
/* finish neighborhood */
|
|
ur = *(pi-cols+1);
|
|
r = *(pi+1);
|
|
br = *(pi+cols+1);
|
|
|
|
findEdge(ul, u, ur, l, c, r, bl, b, br, pe, po, 'S');
|
|
|
|
/* start next neigborhood */
|
|
ul = u; u = ur;
|
|
l = c; c = r;
|
|
bl = b; b = br;
|
|
|
|
}
|
|
/* Clear last pixel */
|
|
*(pe++) = 0; *(po++) = 0; pi++;
|
|
}
|
|
|
|
/* Clear last line */
|
|
for(j=0; j<cols; j++) {
|
|
*(pe++) = 0;
|
|
*(po++) = 0;
|
|
}
|
|
}
|
|
|
|
/*******************************************************************************************
|
|
* Function EdgeGrow
|
|
* Thickens the edge map by considering as an edge any pixel which has an edge pixel in a
|
|
* neighborhood of dimensions sr, sc
|
|
******************************************************************************************/
|
|
unsigned char *sv_H263EdgeGrow(unsigned char *Edge, int rows, int cols, int sr, int sc)
|
|
{
|
|
unsigned char *pse, *pf, *pe, ed, *Fat;
|
|
int du, db, dl, dr, i, j, k, l, sr2, sc2;
|
|
|
|
if (!(Fat = (unsigned char *)ScAlloc(rows*cols))) {
|
|
/* fprintf(stderr,"malloc failed\n"); */
|
|
/* exit(-1); */
|
|
return(NULL);
|
|
}
|
|
|
|
if (!(sr%2) || !(sc%2)) {
|
|
/* printf("Structuring Element must have odd dimensions\n");
|
|
exit(0); */
|
|
return(NULL);
|
|
}
|
|
|
|
sr2 = sr >> 1; sc2 = sc >> 1;
|
|
|
|
pe = Edge;
|
|
pf = Fat;
|
|
for(i=0; i<rows; i++) {
|
|
for(j=0; j<cols; j++, pe++, pf++) {
|
|
|
|
du = i>sr2 ? sr2 : i;
|
|
db = (rows-1-i) > sr2 ? sr2 : (rows-1-i);
|
|
dl = j > sc2 ? sc2 : j;
|
|
dr = (cols-1-j) > sc2 ? sc2 : (cols-1-j);
|
|
|
|
ed = 0;
|
|
for(k=-du; k<=db; k++) {
|
|
pse = pe + k * cols - dl;
|
|
for(l=-dl; l<=dr; l++, pse++) {
|
|
if (ed = *pse) break;
|
|
}
|
|
if(ed) break;
|
|
}
|
|
*pf = ed;
|
|
}
|
|
}
|
|
return Fat;
|
|
}
|