1. 程式人生 > >飛卡之OpenCV影象處理賽道例項

飛卡之OpenCV影象處理賽道例項

普通寫法

程式碼

#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