飛卡之OpenCV影象處理賽道例項
阿新 • • 發佈:2018-12-11
普通寫法
程式碼
#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