zl程序教程

您现在的位置是:首页 >  后端

当前栏目

飞卡之OpenCV图像处理赛道实例

2023-09-11 14:20:36 时间

普通写法

代码

#include "cv.h"
#include "highgui.h"
#include <stdio.h>
#include <string.h>
#include <math.h>
#include "stdlib.h"

#define CAMERA_H  120                            //图片高度
#define CAMERA_W  188                            //图片宽度
#define white 255                                //255对应图像白色
#define black 0                                  //0对应图像黑色

typedef unsigned char uint8;				     //uint8 是单片机程序常用的8位数据类型
uint8 img[CAMERA_H][CAMERA_W] = { 0 };		     //图像所在的数组!!!!!!

IplImage* pImg_1 = NULL;                         //原图图像指针
IplImage* pImg_2 = NULL;	                     //当前图图像指针
char pos[1000];                                  //保存路径的字符数组
void CoverCarhead(void);
void ExtractZone(void);

int main()
{
	/*以下为读取图像,并将图像灰度信息保存在img数组里(不需要理解)*/
	pImg_1 = cvCreateImage(cvSize(CAMERA_W, CAMERA_H), 8, 3);
	cvNamedWindow("原图", 0);//创建窗口
	sprintf(pos, "%d.jpg", 6);///请在此处修改路径!!!如路径为“C:\\桌面\\fiscar\\2.jpg”,修改函数为:sprintf(pos, "C:\\桌面\\fiscar\\%d.jpg", 2);
	//图片如果在工程文件夹中不需要标注路径
	pImg_1 = cvLoadImage(pos, 0);
	cvShowImage("原图", pImg_1);
	CvScalar s;
	int i, j;
	for (i = 0; i<CAMERA_H; i++)
	{
		for (j = 0; j<CAMERA_W; j++)
		{
			s = cvGet2D(pImg_1, i, j);
			img[i][j] = s.val[0];
			if (img[i][j] > 100) img[i][j] = 255;
			else img[i][j] = 0;
		}
	}
	/*以上为读取图像,并将图像灰度信息保存在img数组里(不需要理解)*/

	/*以下为你的代码,提取出的连通域部分请用灰色表示(将灰度值改为100)*/

	CoverCarhead(); //盖住车头
    ExtractZone();  //提取联通域

	/*以上为你的代码,提取出的连通域部分请用灰色表示(将灰度值改为100)*/

	/*以下为显示修改后的图像(不需要理解),按空格结束程序*/
	pImg_2 = cvCreateImage(cvSize(CAMERA_W, CAMERA_H), 8, 3);
	cvNamedWindow("当前图", 0);//创建窗口
	for (i = 0; i<CAMERA_H; i++)
	{
		for (j = 0; j<CAMERA_W; j++)
		{
			s = cvGet2D(pImg_2, i, j);
			s.val[0] = img[i][j];
			s.val[1] = img[i][j];
			s.val[2] = img[i][j];
			cvSet2D(pImg_2, i, j, s);
		}
	}
	cvShowImage("当前图", pImg_2);
	cvWaitKey(0); //等待按键
	/*以上为显示修改后的图像(不需要理解),按空格结束程序*/
}

void example(void)
{
	int line, col;						 //这是一段演示代码,在图像上画了一个灰黑色十字
	for (line = 50; line <= 60; line++)  //这是一段演示代码,在图像上画了一个灰黑色十字
		img[line][94] = 0;               //这是一段演示代码,在图像上画了一个灰黑色十字
	for (line = 60; line <= 70; line++)  //这是一段演示代码,在图像上画了一个灰黑色十字
		img[line][94] = 10;              //这是一段演示代码,在图像上画了一个灰黑色十字
	for (col = 84; col <= 94; col++)     //这是一段演示代码,在图像上画了一个灰黑色十字
		img[60][col] = 127;              //这是一段演示代码,在图像上画了一个灰黑色十字
	for (col = 94; col <= 104; col++)    //这是一段演示代码,在图像上画了一个灰黑色十字
		img[60][col] = 200;              //这是一段演示代码,在图像上画了一个灰黑色十字
}

void CoverCarhead(void)
{
    int i, j;

    for(i=75; i<120; i++)
    {
        for(j=70; j<112; j++)
        {
            img[i][j] = 255;
        }
    }
}

void ExtractZone(void)
{
    int i, j;
    int BorderLeft[120], BorderRight[120], Middle[120];
    int LGetFlag[120], RGetFlag[120];

    for(i=CAMERA_H-1; i>=0; i--)
    {
        BorderLeft[i] = 0;
        BorderRight[i] = 0;
        Middle[i] = 94;
        LGetFlag[i] = 0;
        RGetFlag[i] = 0;
    }

    for(i=CAMERA_H-1; i>=0; i--)
    {
        if(i == CAMERA_H-1)
        {
            //往左
            for(j=94; j>=2; j--)
            {
                if(img[i][j]==white && LGetFlag[i]==0)
                {
                    img[i][j] = 100;
                    if(img[i][j-1]==black && img[i][j-2]==black)
                    {
                        BorderLeft[i] = j-1;
                        LGetFlag[i] = 1;
                    }
                    else
                    {
                        BorderLeft[i] = 2;
                    }
                }
            }
            //往右
            for(j=95; j<=CAMERA_W-3; j++)
            {
                if(img[i][j]==white && RGetFlag[i]==0)
                {
                    img[i][j] = 100;
                    if(img[i][j+1]==black && img[i][j+2]==black)
                    {
                        BorderRight[i] = j+1;
                        RGetFlag[i] = 1;
                    }
                    else
                    {
                        BorderRight[i] = CAMERA_W-3;
                    }
                }
            }
            Middle[i] = (BorderRight[i] + BorderLeft[i]) / 2;
        }
        else
        {
            for(j=Middle[i+1]; j>=2; j--)
            {
                if(img[i][j]==white && LGetFlag[i]==0)
                {
                    img[i][j] = 100;
                    if(img[i][j-1]==black && img[i][j-2]==black)
                    {
                        BorderLeft[i] = j-1;
                        LGetFlag[i] = 1;
                    }
                    else
                    {
                        BorderLeft[i] = 2;
                    }
                }
            }

            for(j=Middle[i+1]+1; j<=CAMERA_W-3; j++)
            {
                if(img[i][j]==white && RGetFlag[i]==0)
                {
                    img[i][j] = 100;
                    if(img[i][j+1]==black && img[i][j+2]==black)
                    {
                        BorderRight[i] = j+1;
                        RGetFlag[i] = 1;
                    }
                    else
                    {
                        BorderRight[i] = CAMERA_W-3;
                    }
                }
            }

            Middle[i] = (BorderRight[i] + BorderLeft[i]) / 2;
        }
    }
}

效果展示

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

上面自己写的这个逐行扫的方式,显然对于3 5 6 7都是不适应的。

然后就有了大神的,连通域写法,但是目前写出的这个连通域运行效率低,还待改进!

连通域写法

代码

#include "cv.h"
#include "highgui.h"
#include <stdio.h>
#include <string.h>
#include <math.h>
#include "stdlib.h"

#define CAMERA_H  120                            //图片高度
#define CAMERA_W  188                            //图片宽度
#define white 255                                //255对应图像白色
#define black 0                                  //0对应图像黑色

typedef unsigned char uint8;				     //uint8 是单片机程序常用的8位数据类型
uint8 img[CAMERA_H][CAMERA_W] = { 0 };		     //图像所在的数组!!!!!!
uint8 new_img[CAMERA_H][CAMERA_W] = { 0 };

IplImage* pImg_1 = NULL;                         //原图图像指针
IplImage* pImg_2 = NULL;	                     //当前图图像指针
char pos[1000];                                  //保存路径的字符数组
void CoverCarhead(void);
void ExtractZone(void);
struct link
{
    int x;
    int y;
    struct link *new_up;
    struct link *new_down;
    struct link *new_left;
    struct link *new_right;
};
void example1(struct link *start_point);

int main()
{
	/*以下为读取图像,并将图像灰度信息保存在img数组里(不需要理解)*/
	pImg_1 = cvCreateImage(cvSize(CAMERA_W, CAMERA_H), 8, 3);
	cvNamedWindow("原图", 0);//创建窗口
	sprintf(pos, "%d.jpg", 6);///请在此处修改路径!!!如路径为“C:\\桌面\\fiscar\\2.jpg”,修改函数为:sprintf(pos, "C:\\桌面\\fiscar\\%d.jpg", 2);
	//图片如果在工程文件夹中不需要标注路径
	pImg_1 = cvLoadImage(pos, 0);
	cvShowImage("原图", pImg_1);
	CvScalar s;
	int i, j;
	for (i = 0; i<CAMERA_H; i++)
	{
		for (j = 0; j<CAMERA_W; j++)
		{
			s = cvGet2D(pImg_1, i, j);
			img[i][j] = s.val[0];
			new_img[i][j] = 0;//新数组初始化
			if (img[i][j] > 100) img[i][j] = 255;
			else img[i][j] = 0;
		}
	}
	/*以上为读取图像,并将图像灰度信息保存在img数组里(不需要理解)*/
    for (i = 74;i < 120;i++)
    {
        for (j = 70;j < 118;j++)
        {
            img[i][j] = 255;
        }
    }
    for (i = 0; i<CAMERA_H; i++)
	{
		for (j = 0; j<CAMERA_W; j++)
		{
            s.val[0] = img[i][j];
            s.val[1] = img[i][j];
            s.val[2] = img[i][j];
			cvSet2D(pImg_1, i, j, s);
		}
	}
    cvShowImage("原图", pImg_1);
	/*以下为你的代码,提取出的连通域部分请用灰色表示(将灰度值改为100)*/

//	CoverCarhead(); //盖住车头
//    ExtractZone();  //提取联通域

    struct link *ptr = NULL;
    ptr = (struct link *)malloc(sizeof(struct link));
    ptr->x = 115;
    ptr->y = 94;
    ptr->new_down = NULL;
    ptr->new_up = NULL;
    ptr->new_left = NULL;
    ptr->new_right = NULL;
    printf("%d,%d\n",ptr->x,ptr->y);
	example1(ptr);//演示代码,编程时请注释

	/*以上为你的代码,提取出的连通域部分请用灰色表示(将灰度值改为100)*/

	/*以下为显示修改后的图像(不需要理解),按空格结束程序*/
	pImg_2 = cvCreateImage(cvSize(CAMERA_W, CAMERA_H), 8, 3);
	cvNamedWindow("当前图", 0);//创建窗口
	for (i = 0; i<CAMERA_H; i++)
	{
		for (j = 0; j<CAMERA_W; j++)
		{
//			s = cvGet2D(pImg_2, i, j);
//			s.val[0] = img[i][j];
//			s.val[1] = img[i][j];
//			s.val[2] = img[i][j];
//			cvSet2D(pImg_2, i, j, s);

			if (new_img[i][j] == 1)
            {
                s.val[0] = 100;
                s.val[1] = 100;
                s.val[2] = 100;
                printf("YSE/n");
            }
            else
            {
                s.val[0] = 0;
                s.val[1] = 0;
                s.val[2] = 0;
            }
			cvSet2D(pImg_2, i, j, s);
		}
	}
	cvShowImage("当前图", pImg_2);
	cvWaitKey(0); //等待按键
	/*以上为显示修改后的图像(不需要理解),按空格结束程序*/
}

void example(void)
{
	int line, col;						 //这是一段演示代码,在图像上画了一个灰黑色十字
	for (line = 50; line <= 60; line++)  //这是一段演示代码,在图像上画了一个灰黑色十字
		img[line][94] = 0;               //这是一段演示代码,在图像上画了一个灰黑色十字
	for (line = 60; line <= 70; line++)  //这是一段演示代码,在图像上画了一个灰黑色十字
		img[line][94] = 10;              //这是一段演示代码,在图像上画了一个灰黑色十字
	for (col = 84; col <= 94; col++)     //这是一段演示代码,在图像上画了一个灰黑色十字
		img[60][col] = 127;              //这是一段演示代码,在图像上画了一个灰黑色十字
	for (col = 94; col <= 104; col++)    //这是一段演示代码,在图像上画了一个灰黑色十字
		img[60][col] = 200;              //这是一段演示代码,在图像上画了一个灰黑色十字
}

void CoverCarhead(void)
{
    int i, j;

    for(i=75; i<120; i++)
    {
        for(j=70; j<112; j++)
        {
            img[i][j] = 255;
        }
    }
}

void ExtractZone(void)
{
    int i, j;
    int BorderLeft[120], BorderRight[120], Middle[120];
    int LGetFlag[120], RGetFlag[120];

    for(i=CAMERA_H-1; i>=0; i--)
    {
        BorderLeft[i] = 0;
        BorderRight[i] = 0;
        Middle[i] = 94;
        LGetFlag[i] = 0;
        RGetFlag[i] = 0;
    }

    for(i=CAMERA_H-1; i>=0; i--)
    {
        if(i == CAMERA_H-1)
        {
            //往左
            for(j=94; j>=2; j--)
            {
                if(img[i][j]==white && LGetFlag[i]==0)
                {
                    img[i][j] = 100;
                    if(img[i][j-1]==black && img[i][j-2]==black)
                    {
                        BorderLeft[i] = j-1;
                        LGetFlag[i] = 1;
                    }
                    else
                    {
                        BorderLeft[i] = 2;
                    }
                }
            }
            //往右
            for(j=95; j<=CAMERA_W-3; j++)
            {
                if(img[i][j]==white && RGetFlag[i]==0)
                {
                    img[i][j] = 100;
                    if(img[i][j+1]==black && img[i][j+2]==black)
                    {
                        BorderRight[i] = j+1;
                        RGetFlag[i] = 1;
                    }
                    else
                    {
                        BorderRight[i] = CAMERA_W-3;
                    }
                }
            }
            Middle[i] = (BorderRight[i] + BorderLeft[i]) / 2;
        }
        else
        {
            for(j=Middle[i+1]; j>=2; j--)
            {
                if(img[i][j]==white && LGetFlag[i]==0)
                {
                    img[i][j] = 100;
                    if(img[i][j-1]==black && img[i][j-2]==black)
                    {
                        BorderLeft[i] = j-1;
                        LGetFlag[i] = 1;
                    }
                    else
                    {
                        BorderLeft[i] = 2;
                    }
                }
            }

            for(j=Middle[i+1]+1; j<=CAMERA_W-3; j++)
            {
                if(img[i][j]==white && RGetFlag[i]==0)
                {
                    img[i][j] = 100;
                    if(img[i][j+1]==black && img[i][j+2]==black)
                    {
                        BorderRight[i] = j+1;
                        RGetFlag[i] = 1;
                    }
                    else
                    {
                        BorderRight[i] = CAMERA_W-3;
                    }
                }
            }

            Middle[i] = (BorderRight[i] + BorderLeft[i]) / 2;
        }
    }
}

void example1(struct link *start_point)
{
    int i,j;
    static int ttt = 0;
    printf("%d,%d\n",start_point->x,start_point->y);
    if (start_point->x < 119&&start_point->x >=1&&start_point->y < 187&&start_point->y >=1)
    {
        ttt++;
        if (new_img[start_point->x][start_point->y] == 1)
        {
            return;
        }
        if (img[start_point->x][start_point->y] == 255)
        {
            new_img[start_point->x][start_point->y] = 1;
            start_point->new_down = (struct link *)malloc(sizeof(struct link));
            start_point->new_up = (struct link *)malloc(sizeof(struct link));
            start_point->new_left = (struct link *)malloc(sizeof(struct link));
            start_point->new_right = (struct link *)malloc(sizeof(struct link));
            start_point->new_down->x = start_point->x + 1;
            start_point->new_down->y = start_point->y;

            start_point->new_down->new_down = NULL;
            start_point->new_down->new_up = NULL;
            start_point->new_down->new_left = NULL;
            start_point->new_down->new_right = NULL;

            start_point->new_up->x = start_point->x - 1;
            start_point->new_up->y = start_point->y;

            start_point->new_up->new_down = NULL;
            start_point->new_up->new_up = NULL;
            start_point->new_up->new_left = NULL;
            start_point->new_up->new_right = NULL;

            start_point->new_left->x = start_point->x;
            start_point->new_left->y = start_point->y + 1;

            start_point->new_left->new_down = NULL;
            start_point->new_left->new_up = NULL;
            start_point->new_left->new_left = NULL;
            start_point->new_left->new_right = NULL;

            start_point->new_right->x = start_point->x;
            start_point->new_right->y = start_point->y - 1;

            start_point->new_right->new_down = NULL;
            start_point->new_right->new_up = NULL;
            start_point->new_right->new_left = NULL;
            start_point->new_right->new_right = NULL;
            //printf("%d,%d\n",start_point->new_down->x,start_point->new_down->y);
            printf("%d,%d\n",start_point->new_up->x,start_point->new_up->y);
            //printf("%d,%d\n",start_point->new_right->x,start_point->new_right->y);
            printf("%d,%d\n",start_point->new_left->x,start_point->new_left->y);

            example1(start_point->new_down);
            example1(start_point->new_up);
            example1(start_point->new_left);
            example1(start_point->new_right);
        }
        else
        {
            return;
        }
    }
    else
        return;
}

效果展示

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述