📄 main.cpp
字号:
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
double M_PI = 3.1415926535897;
typedef struct{
int rows;
int cols;
unsigned char* data;
}sImage;
long getImageInfo(FILE* inputFile, long offset, int numberOfChars){
unsigned char* ptrC;
long value = 0L;
unsigned char dummy = '0';
int i;
ptrC = &dummy;
fseek(inputFile, offset, SEEK_SET);
for(i = 1; i <= numberOfChars; i++){
fread(ptrC, sizeof(char), 1, inputFile);
value = (long)(value + (*ptrC) * (pow(256, (i - 1))));
}
return(value);
}
void copyImageInfo(FILE* inputFile, FILE* outputFile){
unsigned char* ptrC;
unsigned char dummy = '0';
int i;
ptrC = &dummy;
fseek(inputFile, 0L, SEEK_SET);
fseek(outputFile, 0L, SEEK_SET);
for(i = 0; i <= 50; i++){
fread(ptrC, sizeof(char), 1, inputFile);
fwrite(ptrC, sizeof(char), 1, outputFile);
}
}
void copyColorTable(FILE* inputFile, FILE* outputFile, int nColors){
unsigned char* ptrC;
unsigned char dummy = '0';
int i;
ptrC = &dummy;
fseek(inputFile, 54L, SEEK_SET);
fseek(outputFile, 54L, SEEK_SET);
for(i = 0; i <= (4 * nColors); i++){
fread(ptrC, sizeof(char), 1, inputFile);
fwrite(ptrC, sizeof(char), 1, outputFile);
}
}
void CalculateCannyEdgeImage(char* fName){
FILE *bmpInput, *bmpOutput, *gaussOutput;
sImage originalImage, gaussImage, edgeImage;
unsigned int r, c;
int I, J;
int sumX, sumY, SUM;
int leftPixel, rightPixel;
int P1, P2, P3, P4, P5, P6, P7, P8;
int nColors;
unsigned long vectorSize;
unsigned long fileSize;
int MASK[5][5];
int GX[3][3];
int GY[3][3];
unsigned char *pChar, someChar;
unsigned int row, col;
float ORIENT;
int edgeDirection;
int highThreshold, lowThreshold;
someChar = '0';
pChar = &someChar;
//...5x5 Gaussian mask. Ref: http://www.cee.hw.ac.uk/hipr/html/gsmooth.html...
MASK[0][0] = 2; MASK[0][1] = 4; MASK[0][2] = 5; MASK[0][3] = 4; MASK[0][4] = 2;
MASK[1][0] = 4; MASK[1][1] = 9; MASK[1][2] = 12; MASK[1][3] = 9; MASK[1][4] = 4;
MASK[2][0] = 5; MASK[2][1] = 12; MASK[2][2] = 15; MASK[2][3] = 12; MASK[2][4] = 5;
MASK[3][0] = 4; MASK[3][1] = 9; MASK[3][2] = 12; MASK[3][3] = 9; MASK[3][4] = 4;
MASK[4][0] = 2; MASK[4][1] = 4; MASK[4][2] = 5; MASK[4][3] = 4; MASK[4][4] = 2;
//...3x3 GX Sobel mask. Ref: www.cee.hw.ac.uk/hipr/html/sobel.html...
GX[0][0] = -1; GX[0][1] = 0; GX[0][2] = 1;
GX[1][0] = -2; GX[1][1] = 0; GX[1][2] = 2;
GX[2][0] = -1; GX[2][1] = 0; GX[2][2] = 1;
//...3x3 GY Sobel mask. Ref: www.cee.hw.ac.uk/hipr/html/sobel.html...
GY[0][0] = 1; GY[0][1] = 2; GY[0][2] = 1;
GY[1][0] = 0; GY[1][1] = 0; GY[1][2] = 0;
GY[2][0] = -1; GY[2][1] = -2; GY[2][2] = -1;
//...Open files for reading and writing to...
bmpInput = fopen(fName, "rb");
bmpOutput = fopen("canny.bmp", "wb");
gaussOutput = fopen("gauss.bmp", "wb");
//...Start pointer at beginning of file...
fseek(bmpInput, 0L, SEEK_END);
//..Retrieve and print file size and number of cols and rows...
fileSize = getImageInfo(bmpInput, 2, 4);
originalImage.cols = (int)getImageInfo(bmpInput, 18, 4);
originalImage.rows = (int)getImageInfo(bmpInput, 22, 4);
gaussImage.rows = edgeImage.rows = originalImage.rows;
gaussImage.cols = edgeImage.cols = originalImage.cols;
//...Retrieve and print Number of colors...
nColors = (int)getImageInfo(bmpInput, 46, 4);
//...Allocate memory for originalImage.data...
vectorSize = fileSize - (14 + 40 + 4 * nColors);
originalImage.data = (unsigned char*)malloc(vectorSize * sizeof(unsigned char));
if(originalImage.data == NULL){
printf("Failed to malloc originalImage.data\n");
exit(0);
}
//...Allocate memory for gaussImage.data...
//printf("vectorSize: %lu\n", vectorSize);
gaussImage.data = (unsigned char*)malloc(vectorSize * sizeof(unsigned char));
if(gaussImage.data == NULL){
printf("Failed to malloc gaussImage.data\n");
exit(0);
}
//...Allocate memory for edgeImage.data...
edgeImage.data = (unsigned char*)malloc(vectorSize * sizeof(unsigned char));
if(edgeImage.data == NULL){
printf("Failed to malloc edgeImage.data\n");
exit(0);
}
copyImageInfo(bmpInput, bmpOutput);
copyColorTable(bmpInput, bmpOutput, nColors);
copyImageInfo(bmpInput, gaussOutput);
copyColorTable(bmpInput, gaussOutput, nColors);
fseek(bmpInput, (14 + 40 + 4 * nColors), SEEK_SET);
fseek(bmpOutput, (14 + 40 + 4 * nColors), SEEK_SET);
fseek(gaussOutput, (14 + 40 + 4 * nColors), SEEK_SET);
//...Read input.bmp and store it's raster data into originalImage.data...
for(row = 0; row <= originalImage.rows - 1; row++){
for(col = 0; col <= originalImage.cols - 1; col++){
fread(pChar, sizeof(char), 1, bmpInput);
*(originalImage.data + row * originalImage.cols + col) = *pChar;
}
}
/**************************************************
* GAUSSIAN MASK ALGORITHM STARTS HERE *
**************************************************/
for(r = 0; r <= (originalImage.rows - 1); r++){
for(c = 0; c <= (originalImage.cols - 1); c++){
SUM = 0;
//...Image boundaries...
if(r == 0 || r == 1 || r == originalImage.rows - 2 || r == originalImage.rows - 1){
SUM = *pChar;
}
else if(c == 0 || c == 1 || c == originalImage.cols - 2 || c == originalImage.cols - 1){
SUM = *pChar;
}
//...Convolution starts here...
else{
for(I = -2; I <= 2; I++){
for(J = -2; J <= 2; J++){
SUM = SUM + (int)((*(originalImage.data + c + I + (r + J) * originalImage.cols)) * (MASK[I + 2][J + 2]) / 115);
}
}
}
if(SUM > 255){
SUM = 255;
}
if(SUM < 0){
SUM = 0;
}
*(gaussImage.data + c + r * originalImage.cols) = (unsigned char)(SUM);
}
}
/*******************************************
* SOBEL GRADIENT APPROXIMATION *
*******************************************/
for(r = 0; r <= (originalImage.rows - 1); r++){
for(c = 0; c <= (originalImage.cols - 1); c++){
sumX = 0;
sumY = 0;
//...Image boundaries...
if(r == 0 || r == originalImage.rows - 1){
SUM = 0;
}
else if(c == 0 || c == originalImage.cols - 1){
SUM = 0;
}
//...Convolution starts here...
else{
/***************************************
* X gradient approximation *
***************************************/
for(I = -1; I <= 1; I++){
for(J = -1; J <= 1; J++){
sumX = sumX + (int)((*(gaussImage.data + c + I + (r + J) * originalImage.cols)) * GX[I + 1][J + 1]);
}
}
/***************************************
* Y gradient approximation *
***************************************/
for(I = -1; I <= 1; I++){
for(J = -1; J <= 1; J++){
sumY = sumY + (int)((*(gaussImage.data + c + I + (r + J) * originalImage.cols)) * GY[I + 1][J + 1]);
}
}
/*************************************************************
* GRADIENT MAGNITUDE APPROXIMATION (Myler p.218) *
*************************************************************/
SUM = abs(sumX) + abs(sumY);
if(SUM > 255){
SUM = 255;
}
if(SUM < 0){
SUM = 0;
}
/************************************
* Magnitude orientation *
************************************/
//...Cannot divide by zero...
if(sumX == 0){
if(sumY == 0){
ORIENT = 0.0;
}
else if(sumY < 0){
sumY = -sumY;
ORIENT = 90.0;
}
else ORIENT = 90.0;
}
//...Can't take invtan of angle in 2nd Quad...
else if(sumX < 0 && sumY > 0){
sumX = -sumX;
ORIENT = 180 - ((atan((float)(sumY) / (float)(sumX))) * (180 / M_PI));
}
//...Can't take invtan of angle in 4th Quad...
else if(sumX > 0 && sumY < 0){
sumY = -sumY;
ORIENT = 180 - ((atan((float)(sumY) / (float)(sumX))) * (180 / M_PI));
}
//..Else angle is in 1st or 3rd Quad...
else{
ORIENT = (atan((float)(sumY) / (float)(sumX))) * (180 / M_PI);
}
/***************************************************
* Find edgeDirection by assigning ORIENT a value of
* either 0, 45, 90 or 135 degrees, depending on which
* value ORIENT is closest to
****************************************************/
if(ORIENT < 22.5){
edgeDirection = 0;
}
else if(ORIENT < 67.5){
edgeDirection = 45;
}
else if(ORIENT < 112.5){
edgeDirection = 90;
}
else if(ORIENT < 157.5){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -