home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The C Users' Group Library 1994 August
/
wc-cdrom-cusersgrouplibrary-1994-08.iso
/
listings
/
v_09_11
/
cips911.exe
/
EDGE.C
< prev
next >
Wrap
Text File
|
1991-04-13
|
17KB
|
734 lines
/***********************************************
*
* file d:\cips\edge.c
*
* Functions: This file contains
* detect_edges
* setup_masks
* get_edge_options
* perform_convolution
* quick_edge
* fix_edges
*
* Purpose:
* These functions implement several
* types of basic edge detection.
*
* External Calls:
* wtiff.c - does_not_exist
* round_off_image_size
* create_allocate_tiff_file
* write_array_into_tiff_image
* tiff.c - read_tiff_header
* rtiff.c - read_tiff_image
* numcvrt.c - get_integer
*
*
* Modifications:
* 27 January 1991 - created
*
*************************************************/
#include "d:\cips\cips.h"
short quick_mask[3][3] = {
{-1, 0, -1},
{ 0, 4, 0},
{-1, 0, -1} };
/***************************
*
* Directions for the masks
* 3 2 1
* 4 x 0
* 5 6 7
*
****************************/
/* masks for kirsch operator */
short kirsch_mask_0[3][3] = {
{ 5, 5, 5},
{-3, 0, -3},
{-3, -3, -3} };
short kirsch_mask_1[3][3] = {
{-3, 5, 5},
{-3, 0, 5},
{-3, -3, -3} };
short kirsch_mask_2[3][3] = {
{-3, -3, 5},
{-3, 0, 5},
{-3, -3, 5} };
short kirsch_mask_3[3][3] = {
{-3, -3, -3},
{-3, 0, 5},
{-3, 5, 5} };
short kirsch_mask_4[3][3] = {
{-3, -3, -3},
{-3, 0, -3},
{ 5, 5, 5} };
short kirsch_mask_5[3][3] = {
{-3, -3, -3},
{ 5, 0, -3},
{ 5, 5, -3} };
short kirsch_mask_6[3][3] = {
{ 5, -3, -3},
{ 5, 0, -3},
{ 5, -3, -3} };
short kirsch_mask_7[3][3] = {
{ 5, 5, -3},
{ 5, 0, -3},
{-3, -3, -3} };
/* masks for prewitt operator */
short prewitt_mask_0[3][3] = {
{ 1, 1, 1},
{ 1, -2, 1},
{-1, -1, -1} };
short prewitt_mask_1[3][3] = {
{ 1, 1, 1},
{ 1, -2, -1},
{ 1, -1, -1} };
short prewitt_mask_2[3][3] = {
{ 1, 1, -1},
{ 1, -2, -1},
{ 1, 1, -1} };
short prewitt_mask_3[3][3] = {
{ 1, -1, -1},
{ 1, -2, -1},
{ 1, 1, 1} };
short prewitt_mask_4[3][3] = {
{-1, -1, -1},
{ 1, -2, 1},
{ 1, 1, 1} };
short prewitt_mask_5[3][3] = {
{-1, -1, 1},
{-1, -2, 1},
{ 1, 1, 1} };
short prewitt_mask_6[3][3] = {
{-1, 1, 1},
{-1, -2, 1},
{-1, 1, 1} };
short prewitt_mask_7[3][3] = {
{ 1, 1, 1},
{-1, -2, 1},
{-1, -1, 1} };
/* masks for sobel operator */
short sobel_mask_0[3][3] = {
{ 1, 2, 1},
{ 0, 0, 0},
{-1, -2, -1} };
short sobel_mask_1[3][3] = {
{ 2, 1, 0},
{ 1, 0, -1},
{ 0, -1, -2} };
short sobel_mask_2[3][3] = {
{ 1, 0, -1},
{ 2, 0, -2},
{ 1, 0, -1} };
short sobel_mask_3[3][3] = {
{ 0, -1, -2},
{ 1, 0, -1},
{ 2, 1, 0} };
short sobel_mask_4[3][3] = {
{-1, -2, -1},
{ 0, 0, 0},
{ 1, 2, 1} };
short sobel_mask_5[3][3] = {
{-2, -1, 0},
{-1, 0, 1},
{ 0, 1, 2} };
short sobel_mask_6[3][3] = {
{-1, 0, 1},
{-2, 0, 2},
{-1, 0, 1} };
short sobel_mask_7[3][3] = {
{ 0, 1, 2},
{-1, 0, 1},
{-2, -1, 0} };
/**************************************************
*
* detect_edges(...
*
* This function detects edges in an area of one
* image and sends the result to another image
* on disk. It reads the input image from disk,
* calls a convolution function, and then writes
* the result out to disk. If needed, it
* allocates space on disk for the output image.
*
***************************************************/
detect_edges(in_name, out_name, the_image, out_image,
il, ie, ll, le, detect_type, threshold,
high)
char in_name[], out_name[];
int detect_type, high, il, ie,
ll, le, threshold;
short the_image[ROWS][COLS], out_image[ROWS][COLS];
{
int i, j, k, length, width;
struct tiff_header_struct image_header;
if(does_not_exist(out_name)){
read_tiff_header(in_name, &image_header);
round_off_image_size(&image_header,
&length, &width);
image_header.image_length = length*ROWS;
image_header.image_width = width*COLS;
create_allocate_tiff_file(out_name, &image_header,
out_image);
} /* ends if does_not_exist */
read_tiff_image(in_name, the_image, il, ie, ll, le);
read_tiff_header(in_name, &image_header);
perform_convolution(the_image, out_image,
detect_type, threshold,
&image_header, high);
fix_edges(out_image, 1);
write_array_into_tiff_image(out_name, out_image,
il, ie, ll, le);
} /* ends detect_edges */
/**********************************************************
*
* perform_convolution(...
*
* This function performs convolution between the input
* image and 8 3x3 masks. The result is placed in
* the out_image.
*
********************************************************/
perform_convolution(image, out_image,
detect_type, threshold,
image_header, high)
short image[ROWS][COLS],
out_image[ROWS][COLS];
int detect_type, high, threshold;
struct tiff_header_struct *image_header;
{
int a,
b,
i,
is_present,
j,
sum;
short mask_0[3][3],
mask_1[3][3],
mask_2[3][3],
mask_3[3][3],
mask_4[3][3],
mask_5[3][3],
mask_6[3][3],
mask_7[3][3],
max,
min,
new_hi,
new_low;
setup_masks(detect_type, mask_0, mask_1,
mask_2, mask_3, mask_4, mask_5,
mask_6, mask_7);
new_hi = 250;
new_low = 16;
if(image_header->bits_per_pixel == 4){
new_hi = 10;
new_low = 3;
}
min = 0;
max = 255;
if(image_header->bits_per_pixel == 4)
max = 16;
/* clear output image array */
for(i=0; i<ROWS; i++)
for(j=0; j<COLS; j++)
out_image[i][j] = 0;
printf("\n ");
for(i=1; i<ROWS-1; i++){
if( (i%10) == 0) printf("%3d", i);
for(j=1; j<COLS-1; j++){
/* Convolve for all 8 directions */
/* 0 direction */
sum = 0;
for(a=-1; a<2; a++){
for(b=-1; b<2; b++){
sum = sum + image[i+a][j+b] *
mask_0[a+1][b+1];
}
}
if(sum > max) sum = max;
if(sum < 0) sum = 0;
out_image[i][j] = sum;
/* 1 direction */
sum = 0;
for(a=-1; a<2; a++){
for(b=-1; b<2; b++){
sum = sum + image[i+a][j+b] * mask_1[a+1][b+1];
}
}
if(sum > max) sum = max;
if(sum < 0) sum = 0;
out_image[i][j] = sum;
/* 2 direction */
sum = 0;
for(a=-1; a<2; a++){
for(b=-1; b<2; b++){
sum = sum + image[i+a][j+b] * mask_2[a+1][b+1];
}
}
if(sum > max) sum = max;
if(sum < 0) sum = 0;
out_image[i][j] = sum;
/* 3 direction */
sum = 0;
for(a=-1; a<2; a++){
for(b=-1; b<2; b++){
sum = sum + image[i+a][j+b] * mask_3[a+1][b+1];
}
}
if(sum > max) sum = max;
if(sum < 0) sum = 0;
out_image[i][j] = sum;
/* 4 direction */
sum = 0;
for(a=-1; a<2; a++){
for(b=-1; b<2; b++){
sum = sum + image[i+a][j+b] * mask_4[a+1][b+1];
}
}
if(sum > max) sum = max;
if(sum < 0) sum = 0;
out_image[i][j] = sum;
/* 5 direction */
sum = 0;
for(a=-1; a<2; a++){
for(b=-1; b<2; b++){
sum = sum + image[i+a][j+b] * mask_5[a+1][b+1];
}
}
if(sum > max) sum = max;
if(sum < 0) sum = 0;
out_image[i][j] = sum;
/* 6 direction */
sum = 0;
for(a=-1; a<2; a++){
for(b=-1; b<2; b++){
sum = sum + image[i+a][j+b] * mask_6[a+1][b+1];
}
}
if(sum > max) sum = max;
if(sum < 0) sum = 0;
out_image[i][j] = sum;
/* 7 direction */
sum = 0;
for(a=-1; a<2; a++){
for(b=-1; b<2; b++){
sum = sum + image[i+a][j+b] * mask_7[a+1][b+1];
}
}
if(sum > max) sum = max;
if(sum < 0) sum = 0;
out_image[i][j] = sum;
} /* ends loop over j */
} /* ends loop over i */
/* if desired, threshold the output image */
if(threshold == 1){
for(i=0; i<ROWS; i++){
for(j=0; j<COLS; j++){
if(out_image[i][j] > high){
out_image[i][j] = new_hi;
}
else{
out_image[i][j] = new_low;
}
}
}
} /* ends if threshold == 1 */
} /* ends perform_convolution */
/*******************************************
*
* quick_edge(...
*
* This function finds edges by using
* a single 3x3 mask.
*
*******************************************/
quick_edge(in_name, out_name, the_image, out_image,
il, ie, ll, le, threshold, high)
char in_name[], out_name[];
int high, il, ie, ll, le, threshold;
short the_image[ROWS][COLS], out_image[ROWS][COLS];
{
int a, b, i, j, k,
length, max, new_hi, new_low,
sum, width;
struct tiff_header_struct image_header;
if(does_not_exist(out_name)){
printf("\n\n output file does not exist %s", out_name);
read_tiff_header(in_name, &image_header);
round_off_image_size(&image_header,
&length, &width);
image_header.image_length = length*ROWS;
image_header.image_width = width*COLS;
create_allocate_tiff_file(out_name, &image_header,
out_image);
} /* ends if does_not_exist */
read_tiff_header(in_name, &image_header);
new_hi = 250;
new_low = 16;
if(image_header.bits_per_pixel == 4){
new_hi = 10;
new_low = 3;
}
max = 255;
if(image_header.bits_per_pixel == 4)
max = 16;
read_tiff_image(in_name, the_image, il, ie, ll, le);
/* Do convolution over image array */
printf("\n");
for(i=1; i<ROWS-1; i++){
if( (i%10) == 0) printf("%d ", i);
for(j=1; j<COLS-1; j++){
sum = 0;
for(a=-1; a<2; a++){
for(b=-1; b<2; b++){
sum = sum +
the_image[i+a][j+b] *
quick_mask[a+1][b+1];
}
}
if(sum < 0) sum = 0;
if(sum > max) sum = max;
out_image[i][j] = sum;
} /* ends loop over j */
} /* ends loop over i */
/* if desired, threshold the output image */
if(threshold == 1){
for(i=0; i<ROWS; i++){
for(j=0; j<COLS; j++){
if(out_image[i][j] > high){
out_image[i][j] = new_hi;
}
else{
out_image[i][j] = new_low;
}
}
}
} /* ends if threshold == 1 */
fix_edges(out_image, 1);
write_array_into_tiff_image(out_name, out_image,
il, ie, ll, le);
} /* ends quick_edge */
/***********************************************
*
* setup_masks(...
*
* This function copies the mask values defined
* at the top of this file into the mask
* arrays mask_0 through mask_7.
*
***********************************************/
setup_masks(detect_type, mask_0, mask_1, mask_2, mask_3,
mask_4, mask_5, mask_6, mask_7)
int detect_type;
short mask_0[3][3],
mask_1[3][3],
mask_2[3][3],
mask_3[3][3],
mask_4[3][3],
mask_5[3][3],
mask_6[3][3],
mask_7[3][3];
{
int i, j;
if(detect_type == KIRSCH){
for(i=0; i<3; i++){
for(j=0; j<3; j++){
mask_0[i][j] = kirsch_mask_0[i][j];
mask_1[i][j] = kirsch_mask_1[i][j];
mask_2[i][j] = kirsch_mask_2[i][j];
mask_3[i][j] = kirsch_mask_3[i][j];
mask_4[i][j] = kirsch_mask_4[i][j];
mask_5[i][j] = kirsch_mask_5[i][j];
mask_6[i][j] = kirsch_mask_6[i][j];
mask_7[i][j] = kirsch_mask_7[i][j];
}
}
} /* ends if detect_type == KIRSCH */
if(detect_type == PREWITT){
for(i=0; i<3; i++){
for(j=0; j<3; j++){
mask_0[i][j] = prewitt_mask_0[i][j];
mask_1[i][j] = prewitt_mask_1[i][j];
mask_2[i][j] = prewitt_mask_2[i][j];
mask_3[i][j] = prewitt_mask_3[i][j];
mask_4[i][j] = prewitt_mask_4[i][j];
mask_5[i][j] = prewitt_mask_5[i][j];
mask_6[i][j] = prewitt_mask_6[i][j];
mask_7[i][j] = prewitt_mask_7[i][j];
}
}
} /* ends if detect_type == PREWITT */
if(detect_type == SOBEL){
for(i=0; i<3; i++){
for(j=0; j<3; j++){
mask_0[i][j] = sobel_mask_0[i][j];
mask_1[i][j] = sobel_mask_1[i][j];
mask_2[i][j] = sobel_mask_2[i][j];
mask_3[i][j] = sobel_mask_3[i][j];
mask_4[i][j] = sobel_mask_4[i][j];
mask_5[i][j] = sobel_mask_5[i][j];
mask_6[i][j] = sobel_mask_6[i][j];
mask_7[i][j] = sobel_mask_7[i][j];
}
}
} /* ends if detect_type == SOBEL */
} /* ends setup_masks */
/***********************************************
*
* get_edge_options(...
*
* This function queries the user for the
* parameters need to perform edge
* detection.
*
***********************************************/
get_edge_options(detect_type, threshold, high)
int *detect_type, *high, *threshold;
{
int not_finished, response;
not_finished = 1;
while(not_finished){
printf("\nThe Edge Detector options are:\n");
printf("\n\t1. Type of edge detector is %d", *detect_type);
printf("\n\t (recall 1=Prewitt 2=Kirsch 3=Sobel
4=quick)");
printf("\n\t2. Threshold output is %d (0=off 1=on)",
*threshold);
printf("\n\t3. High threshold is %d", *high);
printf("\n\nEnter choice (0 = no change) _\b");
get_integer(&response);
if(response == 0){
not_finished = 0;
}
if(response == 1){
printf("\n\nEnter type of edge detector");
printf("\n (recall 1=Prewitt 2=Kirsch 3=Sobel 4=quick)");
printf("\n _\b");
get_integer(detect_type);
}
if(response == 2){
printf("\n\nEnter threshold output (0=off 1=on)");
printf("\n _\b");
get_integer(threshold);
}
if(response == 3){
printf("\n\nEnter high threshold");
printf("\n _\b");
get_integer(high);
}
} /* ends while not_finished */
} /* ends get_edge_options */
/***********************************************
*
* fix_edges(...
*
* This function fixes the edges of an image
* array after convolution was performed.
* It copies the points near the edge of the
* array out to the edge of the array.
*
***********************************************/
fix_edges(im, w)
int w;
short im[ROWS][COLS];
{
int i, j;
/* four corners */
for(i=w; i>0; i--){
im[i-1][i-1] = im[i][i];
im[i-1][COLS-(i-1)] = im[i][COLS-1-(i-1)];
im[ROWS-(i-1)][i-1] = im[ROWS-1-(i-1)][i];
im[ROWS-(i-1)][COLS-(i-1)] = im[ROWS-1-(i-1)][COLS-1-(i-1)];
} /* ends four corners loop */
for(i=0; i<ROWS; i++){
for(j=w; j>0; j--){
im[i][j-1] = im[i][j];
im[i][COLS-j] = im[i][COLS-j-1];
}
}
for(j=0; j<COLS; j++){
for(i=w; i>0; i--){
im[i-1][j] = im[i][j];
im[ROWS-i][j] = im[ROWS-i-1][j];
}
}
} /* ends fix_edges */