1. 生成左右相机拍摄的3个彩色靶标的图像
两个相机在x轴方向上平移
// 生成左右相机拍摄3个靶标时的图像 生成彩色靶标
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
// 图像尺寸
#define WIDTH 1920
#define HEIGHT 1080
// BMP头信息
#pragma pack(1)
typedef struct {
unsigned short bfType; // 文件类型
unsigned int bfSize; // 文件大小
unsigned short bfReserved1; // 保留字段
unsigned short bfReserved2; // 保留字段
unsigned int bfOffBits; // 到图像数据的偏移
} BITMAPFILEHEADER;
typedef struct {
unsigned int biSize; // DIB头大小
int biWidth; // 图像宽度
int biHeight; // 图像高度
unsigned short biPlanes; // 颜色平面数
unsigned short biBitCount; // 每个像素的位数
unsigned int biCompression; // 压缩类型
unsigned int biSizeImage; // 图像大小
int biXPelsPerMeter; // 水平分辨率
int biYPelsPerMeter; // 垂直分辨率
unsigned int biClrUsed; // 颜色表中使用的颜色数
unsigned int biClrImportant; // 重要的颜色数
} BITMAPINFOHEADER;
// 3D点结构体
typedef struct {
float x, y, z;
} Point3D;
// 相机结构体
typedef struct {
float focal_length; // 焦距
float cx, cy; // 图像中心
} Camera;
// 投影函数,将3D点投影到2D平面
void projectPoint(Camera cam, Point3D pt, int* u, int* v) {
// 投影公式: u = fx * X / Z + cx, v = fy * Y / Z + cy
*u = (int)(cam.focal_length * pt.x / pt.z + cam.cx);
*v = (int)(cam.focal_length * pt.y / pt.z + cam.cy);
}
// 绘制一个圆 生成彩色圆形靶标
void drawCircle(unsigned char* image, int imgWidth, int imgHeight, int x0, int y0, int radius, unsigned char r, unsigned char g, unsigned char b) {
for (int y = -radius; y <= radius; y++) {
for (int x = -radius; x <= radius; x++) {
if (x * x + y * y <= radius * radius) {
int imgX = x0 + x;
int imgY = y0 + y;
if (imgX >= 0 && imgX < imgWidth && imgY >= 0 && imgY < imgHeight) {
int index = (imgY * imgWidth + imgX) * 3;
image[index + 0] = b; // 蓝色
image[index + 1] = g; // 绿色
image[index + 2] = r; // 红色
}
}
}
}
}
// 保存为BMP文件
void saveBMP(const char* filename, unsigned char* image, int width, int height) {
BITMAPFILEHEADER fileHeader;
BITMAPINFOHEADER infoHeader;
fileHeader.bfType = 0x4D42; // "BM"
fileHeader.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + width * height * 3;
fileHeader.bfReserved1 = 0;
fileHeader.bfReserved2 = 0;
fileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
infoHeader.biSize = sizeof(BITMAPINFOHEADER);
infoHeader.biWidth = width;
infoHeader.biHeight = height;
infoHeader.biPlanes = 1;
infoHeader.biBitCount = 24;
infoHeader.biCompression = 0;
infoHeader.biSizeImage = width * height * 3;
infoHeader.biXPelsPerMeter = 0;
infoHeader.biYPelsPerMeter = 0;
infoHeader.biClrUsed = 0;
infoHeader.biClrImportant = 0;
FILE* file = fopen(filename, "wb");
fwrite(&fileHeader, sizeof(BITMAPFILEHEADER), 1, file);
fwrite(&infoHeader, sizeof(BITMAPINFOHEADER), 1, file);
fwrite(image, 3, width * height, file);
fclose(file);
}
int main() {
// 创建空白图像(黑色背景)
unsigned char* imageLeft = (unsigned char*)calloc(WIDTH * HEIGHT * 3, sizeof(unsigned char));
unsigned char* imageRight = (unsigned char*)calloc(WIDTH * HEIGHT * 3, sizeof(unsigned char));
// 定义相机参数
Camera leftCam = { 1000.0f, WIDTH / 2.0f, HEIGHT / 2.0f }; // 左相机
Camera rightCam = { 1000.0f, WIDTH / 2.0f, HEIGHT / 2.0f }; // 右相机(假设右相机位置平移)
// 定义3个圆形靶标的3D坐标
Point3D targets[3] = {
{ 0, 0, 100 },
{ 10, 10, 120 },
{ -10, -10, 110 }
};
// 投影靶标到左相机的图像平面
for (int i = 0; i < 3; i++) {
int u, v;
projectPoint(leftCam, targets[i], &u, &v);
drawCircle(imageLeft, WIDTH, HEIGHT, u, v, 50, 255, 0, 0); // 在左图像上绘制红色靶标
}
// 投影靶标到右相机的图像平面(假设右相机沿X轴平移)
for (int i = 0; i < 3; i++) {
int u, v;
targets[i].x -= 20; // 模拟右相机的平移
projectPoint(rightCam, targets[i], &u, &v);
drawCircle(imageRight, WIDTH, HEIGHT, u, v, 50, 0, 255, 0); // 在右图像上绘制绿色靶标
}
// 保存为BMP图像
saveBMP("left_camera.bmp", imageLeft, WIDTH, HEIGHT);
saveBMP("right_camera.bmp", imageRight, WIDTH, HEIGHT);
// 释放内存
free(imageLeft);
free(imageRight);
printf("保存成功!\n");
return 0;
}
生成图像如下(左相机图像+右相机图像):
如果想要生成白色靶标只需要将,R、G、B分量的参数改为255即可,代码如下:
void drawCircle(unsigned char* image, int imgWidth, int imgHeight, int x0, int y0, int radius) {
for (int y = -radius; y <= radius; y++) {
for (int x = -radius; x <= radius; x++) {
if (x * x + y * y <= radius * radius) {
int imgX = x0 + x;
int imgY = y0 + y;
if (imgX >= 0 && imgX < imgWidth && imgY >= 0 && imgY < imgHeight) {
int index = (imgY * imgWidth + imgX) * 3;
image[index + 0] = 255; // 蓝色分量(255表示白色)
image[index + 1] = 255; // 绿色分量
image[index + 2] = 255; // 红色分量
}
}
}
}
}
生成图像如下(左相机图像+右相机图像):
2. 生成4个白色靶标,其余部分为黑色背景
每张图像中包含两个靶标,第一组左右相机拍摄的图像包含靶标1和2,第二组包含靶标3和4。同时输出生成靶标的位置。
// 生成左右两个相机拍摄的两张靶标图像 每张图像中有2个挨着的圆形靶标
// 左右相机第一张图像对应靶标1和2 第二张图像对应靶标3和4
// 左相机图像1 靶标1坐标: (960, 540)
// 左相机图像1 靶标2坐标 : (1043, 623)
// 左相机图像2 靶标3坐标 : (869, 449)
// 左相机图像2 靶标4坐标 : (1113, 386)
// 右相机图像1 靶标1坐标 : (760, 540)
// 右相机图像1 靶标2坐标 : (876, 623)
// 右相机图像2 靶标3坐标 : (687, 449)
// 右相机图像2 靶标4坐标 : (960, 386)
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
// 图像尺寸
#define WIDTH 1920
#define HEIGHT 1080
// BMP头信息
#pragma pack(1)
typedef struct {
unsigned short bfType; // 文件类型
unsigned int bfSize; // 文件大小
unsigned short bfReserved1; // 保留字段
unsigned short bfReserved2; // 保留字段
unsigned int bfOffBits; // 到图像数据的偏移
} BITMAPFILEHEADER;
typedef struct {
unsigned int biSize; // DIB头大小
int biWidth; // 图像宽度
int biHeight; // 图像高度
unsigned short biPlanes; // 颜色平面数
unsigned short biBitCount; // 每个像素的位数
unsigned int biCompression; // 压缩类型
unsigned int biSizeImage; // 图像大小
int biXPelsPerMeter; // 水平分辨率
int biYPelsPerMeter; // 垂直分辨率
unsigned int biClrUsed; // 颜色表中使用的颜色数
unsigned int biClrImportant; // 重要的颜色数
} BITMAPINFOHEADER;
// 3D点结构体
typedef struct {
float x, y, z;
} Point3D;
// 相机结构体
typedef struct {
float focal_length; // 焦距
float cx, cy; // 图像中心
} Camera;
// 投影函数,将3D点投影到2D平面
void projectPoint(Camera cam, Point3D pt, int* u, int* v) {
*u = (int)(cam.focal_length * pt.x / pt.z + cam.cx);
*v = (int)(cam.focal_length * pt.y / pt.z + cam.cy);
}
// 绘制一个圆
void drawCircle(unsigned char* image, int imgWidth, int imgHeight, int x0, int y0, int radius) {
for (int y = -radius; y <= radius; y++) {
for (int x = -radius; x <= radius; x++) {
if (x * x + y * y <= radius * radius) {
int imgX = x0 + x;
int imgY = y0 + y;
if (imgX >= 0 && imgX < imgWidth && imgY >= 0 && imgY < imgHeight) {
int index = (imgY * imgWidth + imgX) * 3;
image[index + 0] = 255; // 蓝色分量(255表示白色)
image[index + 1] = 255; // 绿色分量
image[index + 2] = 255; // 红色分量
}
}
}
}
}
// 保存为BMP文件
void saveBMP(const char* filename, unsigned char* image, int width, int height) {
BITMAPFILEHEADER fileHeader;
BITMAPINFOHEADER infoHeader;
fileHeader.bfType = 0x4D42; // "BM"
fileHeader.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + width * height * 3;
fileHeader.bfReserved1 = 0;
fileHeader.bfReserved2 = 0;
fileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
infoHeader.biSize = sizeof(BITMAPINFOHEADER);
infoHeader.biWidth = width;
infoHeader.biHeight = height;
infoHeader.biPlanes = 1;
infoHeader.biBitCount = 24;
infoHeader.biCompression = 0;
infoHeader.biSizeImage = width * height * 3;
infoHeader.biXPelsPerMeter = 0;
infoHeader.biYPelsPerMeter = 0;
infoHeader.biClrUsed = 0;
infoHeader.biClrImportant = 0;
FILE* file = fopen(filename, "wb");
fwrite(&fileHeader, sizeof(BITMAPFILEHEADER), 1, file);
fwrite(&infoHeader, sizeof(BITMAPINFOHEADER), 1, file);
fwrite(image, 3, width * height, file);
fclose(file);
}
int main() {
// 创建空白图像(黑色背景)
unsigned char* imageLeft1 = (unsigned char*)calloc(WIDTH * HEIGHT * 3, sizeof(unsigned char));
unsigned char* imageLeft2 = (unsigned char*)calloc(WIDTH * HEIGHT * 3, sizeof(unsigned char));
unsigned char* imageRight1 = (unsigned char*)calloc(WIDTH * HEIGHT * 3, sizeof(unsigned char));
unsigned char* imageRight2 = (unsigned char*)calloc(WIDTH * HEIGHT * 3, sizeof(unsigned char));
// 定义相机参数
Camera leftCam = { 1000.0f, WIDTH / 2.0f, HEIGHT / 2.0f }; // 左相机
Camera rightCam = { 1000.0f, WIDTH / 2.0f, HEIGHT / 2.0f }; // 右相机
// 定义4个圆形靶标的3D坐标
Point3D targets[4] = {
{ 0, 0, 100 }, // 靶标1
{ 10, 10, 120 }, // 靶标2
{ -10, -10, 110 }, // 靶标3
{ 20, -20, 130 } // 靶标4
};
// 左相机图像1:靶标1和靶标2
for (int i = 0; i < 2; i++) {
int u, v;
projectPoint(leftCam, targets[i], &u, &v);
drawCircle(imageLeft1, WIDTH, HEIGHT, u, v, 50); // 在左图像上绘制白色靶标
printf("左相机图像1 靶标%d坐标: (%d, %d)\n", i + 1, u, v); // 输出坐标
}
// 左相机图像2:靶标3和靶标4
for (int i = 2; i < 4; i++) {
int u, v;
projectPoint(leftCam, targets[i], &u, &v);
drawCircle(imageLeft2, WIDTH, HEIGHT, u, v, 50); // 在左图像上绘制白色靶标
printf("左相机图像2 靶标%d坐标: (%d, %d)\n", i + 1, u, v); // 输出坐标
}
// 右相机图像1:靶标1和靶标2(右相机平移X轴)
for (int i = 0; i < 2; i++) {
int u, v;
Point3D shiftedTarget = targets[i]; // 拷贝原始坐标
shiftedTarget.x -= 20; // 模拟右相机平移
projectPoint(rightCam, shiftedTarget, &u, &v);
drawCircle(imageRight1, WIDTH, HEIGHT, u, v, 50); // 在右图像上绘制白色靶标
printf("右相机图像1 靶标%d坐标: (%d, %d)\n", i + 1, u, v); // 输出坐标
}
// 右相机图像2:靶标3和靶标4
for (int i = 2; i < 4; i++) {
int u, v;
Point3D shiftedTarget = targets[i]; // 拷贝原始坐标
shiftedTarget.x -= 20; // 模拟右相机平移
projectPoint(rightCam, shiftedTarget, &u, &v);
drawCircle(imageRight2, WIDTH, HEIGHT, u, v, 50); // 在右图像上绘制白色靶标
printf("右相机图像2 靶标%d坐标: (%d, %d)\n", i + 1, u, v); // 输出坐标
}
// 保存为BMP图像
saveBMP("left_camera1.bmp", imageLeft1, WIDTH, HEIGHT);
saveBMP("left_camera2.bmp", imageLeft2, WIDTH, HEIGHT);
saveBMP("right_camera1.bmp", imageRight1, WIDTH, HEIGHT);
saveBMP("right_camera2.bmp", imageRight2, WIDTH, HEIGHT);
// 释放内存
free(imageLeft1);
free(imageLeft2);
free(imageRight1);
free(imageRight2);
printf("图像保存成功!\n");
return 0;
}
图像如下所示(依次是left_camera1.bmp,left_camera2.bmp,right_camera1.bmp,right_camera1.bmp):