图像处理基础

学习

Posted by simplex on June 7, 2021

**1. 写出图像处理、图像分析、计算机图形学、机器视觉、深度学习、图像测量、图像识别、体视、光圈、景深、运动模糊、pixel、fps、dpi、二值图像等概念的定义及其对应的中英文 **

图像处理:image processing 用计算机对图像进行分析,以达到所需结果的技术。输入是图像数据,输出也是图像数据。

图像分析:Image analysis 一般利用数学模型并结合图像处理的技术来分析底层特征和上层结构,从而提取具有一定智能性的信息。输入是图像数据,输出是可描述性数据。

计算机图形学:computer graphic输入是可描述性数据,输出是图像数据。是一种使用数学算法将二维或三维图形转化为计算机显示器的栅格形式的科学。

机器视觉: machine vision是图像采集、图像处理和图像分析的应用,是使用图像测量代替人眼目测,其核心是图像测量。

机器学习: machine learning 一种技术,它可以从图像数据中学习到知识和实现认知,也可以被用在机器视觉应用中。专门研究计算机怎样模拟或实现人类的学习行为,以获取新的知识或技能,重新组织已有的知识结构使之不断改善自身的性能。

pixel:像素 组成图像的最小单位

fps: 帧每秒(帧数)每秒钟图片的帧数

dpi:每英寸点数 每一英寸长度中,取样、可显示或输出点的数目

二值图像:Binary Image 指将图像上的每一个像素只有两种可能的取值或灰度等级状态

深度学习: deep learning 深度学习的概念源于人工神经网络的研究,含多个隐藏层的多层感知器就是一种深度学习结构。深度学习通过组合低层特征形成更加抽象的高层表示属性类别或特征,以发现数据的分布式特征表示。研究深度学习的动机在于建立模拟人脑进行分析学习的神经网络,它模仿人脑的机制来解释数据。

体视: stereology 借助计算机及数据处理系统和显微镜及显做成像系统,将二维平面经过成像及计算机分析处理得到三维形态,以准确地对物体进行定量及形态结构分析

光圈:Aperture是一个用来控制光线透过镜头,进入机身内感光面光量的装置

景深: DOF 是指在摄影机镜头或其他成像器前沿能够取得清晰图像的成像所测定的被摄物体前后距离范围。

运动模糊: motion blur 运动模糊指的是在曝光期间物体和相机发生了相对位移。

2. 学习.bmp文件的格式,一般是文件信息描述、数据信息描述、调色板、图像数据4个部分组成,彩色图像没有调色板。什么是调色板?什么是伪彩色?是如何实现的?用C/C++编程实现一幅灰度图像bmp文件H0101Gry.bmp和彩色图像bmp文件H0102Rgb.bmp的读取、反相以及灰度图像H0101Gry.bmp的伪彩色,将处理结果图像保存成bmp文件。

调色板:如使用索引来表示图像,调色板就是索引与其对应的颜色的映射表

伪彩色:每个像素的颜色不是由每个基色分量的数值直接决定,而是把像素值当作彩色查找表的表项入口地址,去查找一个显示图像时使用的R,G,B强度值,用查找出的R,G,B强度值产生的彩色称为伪彩色。如果图像中的颜色在调色板或彩色查找表中不存在,则调色板会用一个最为接近的颜色来匹配。

伪彩色处理主要是把黑白的灰度图像或者多波段图像转换为彩色图像的技术过程。调色板中的颜色可以自己设置,或者使用现有的。 | | | | :———————————————————– | :———————————————————– | | H0101Gry_invert_pesudo灰度图取反+伪色彩 | H0101Gry_pesudo灰度图伪色彩 | | H0102Rgb_invert彩图取反 | H0101Gry_invert灰度图取反 |

int main()
{
	bmpConverter bmpCvt = bmpConverter("./pic/H0101Gry.bmp");
	bmpCvt.Img2Bmp("./pic/H0101Gry_pesudo.bmp", 8, 'k');
	bmpCvt.InvertImg();
	bmpCvt.Img2Bmp("./pic/H0101Gry_invert.bmp",8);
	bmpCvt.Img2Bmp("./pic/H0101Gry_invert_pesudo.bmp", 8, 'k');
	bmpCvt.BmpFile2Img("./pic/H0102Rgb.bmp");
	bmpCvt.InvertImg();
	bmpCvt.Img2Bmp("./pic/H0102Rgb_invert.bmp", 0);
	return 0;
}
// 取反图像
void bmpConverter::InvertImg()
{
	//BYTE *pCur, *pEnd = pImg + width * height * channel;
	//for (pCur = pImg; pCur < pEnd; pCur++) *pCur = ~ *pCur;
	int sum = width * height * channel;
	int res = sum - sum / 4 * 4;
	int *pCur= (int *)pImg, *pEnd = (int *)(pImg + sum - res);
	while(pCur < pEnd) *(pCur++) = ~*pCur;
	BYTE * pRes = (BYTE *)pEnd;
	// 将不到一个4个字节的数据逐字节取反
	while(res--)*(pRes++) = ~*(pRes);
	return;
}

// 读取图片
bool bmpConverter::BmpFile2Img(const char * DstFile)
{
	// 如果原先指针不空,则回收内存
	if (pImg)delete pImg;
	//BmpHeader记录的真实的宽度,
	//读出的是真实的宽度,去掉了4对齐的扩展.
	FILE *fp;
	unsigned int size;
	int Suc = 1, w, h;
	int k, extend, tmp[4], err_type;

	// Open File
	width = height = 0;
	if (err_type = fopen_s(&fp, DstFile, "rb"))
	{
		printf("error type: %d \n", err_type);
		return false;
	}
	// Read Struct Info
	if (fread((void *)&FileHeader, 1, sizeof(FileHeader), fp) != sizeof(FileHeader)) Suc = 0;
	if (fread((void *)&BmpHeader, 1, sizeof(BmpHeader), fp) != sizeof(BmpHeader)) Suc = 0;
	if (!Suc ||
		(FileHeader.bfOffBits < sizeof(FileHeader) + sizeof(BmpHeader))
		)
	{
		fclose(fp);
		return false;
	}
	// Read Image Data
	width = w = BmpHeader.biWidth;
	height = h = BmpHeader.biHeight;
	if (BmpHeader.biBitCount < 16)channel = 1;
	else channel = BmpHeader.biBitCount / 8;
#ifdef DEBUG
	printf("读取%d通道图像, 每个像素比特数%d\n", channel, int(BmpHeader.biBitCount));
#endif // DEBUG
	// 无法处理1,4bit的问题
	w = w * channel; // 真实的比特数
	extend = (w + 3) / 4 * 4 - w;
	if (!(size = BmpHeader.biSizeImage)) size = width * height * channel;
	
	fseek(fp, FileHeader.bfOffBits, SEEK_SET);
	if ((pImg = new BYTE[size]) != nullptr)
	{
		for (int i = 1; i <= h; i++)  // 0,1,2,3,4(5): 400-499
		{
			if ((int)fread(pImg + (h - i)*w, sizeof(BYTE), w, fp) != w)
			{
				fclose(fp);
				delete pImg;
				pImg = NULL;
				return false;
			}
			//读掉扩充的数据
			if (fread(&tmp, 1, extend, fp) != extend)
			{
				fclose(fp);
				delete pImg;
				pImg = nullptr;
				return false;

			}
		}
	}
	fclose(fp);
	return true;
}

bool bmpConverter::Img2Bmp(const char * DstFile, int bitCnt, char RGB_MOD)
{
	if (pImg == nullptr)
	{
		// 未读取图像
		puts("保存失败,未读取图像");
		return false;
	}
	bool ret = false;
	switch (bitCnt)
	{
	case 0:
		ret = Img2Bmp(DstFile, BmpHeader.biBitCount, RGB_MOD);
		break;
	case 8:
		ret = Img28bitBmp(DstFile, RGB_MOD);
		break;
	case 24:
		ret = Img224bitBmp(DstFile);
		break;
	default:
		puts("无法处理的位宽");
		break;
	}
	return ret;
}


bmpConverter::~bmpConverter()
{
	if (pImg != nullptr)delete pImg;
}

bool bmpConverter::Img28bitBmp(const char * DstFile, char mod)
{
#ifdef DEBUG
	printf("正在保存8bit 图像 %s\n", DstFile);
#endif // DEBUG
	BYTE * temp_save=nullptr;
	if (channel == 3)
	{
		int sum = width * height;
		temp_save = new BYTE[sum];
		BYTE * p1 = temp_save, *p2 = pImg - 1;
		while (sum--)*(p1++) = (*(++p2) + *(++p2) + *(++p2)) / 3;
		swap(temp_save, pImg);
	}

	//BmpHeader记录的真实的宽度
	//当每行字节个数不是4的倍数时,需要进行4对齐
	FILE * fp;
	int i, extend;
	bool Suc = true;
	BYTE p[4], *pCur;

	// Open File
	if (fopen_s(&fp, DstFile, "w+b")) { return false; }
	// Fill the FileHeader
	FileHeader.bfType = ((WORD)('M' << 8) | 'B');
	FileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + 256 * 4L;
	FileHeader.bfSize = FileHeader.bfOffBits + width * height;
	FileHeader.bfReserved1 = 0;
	FileHeader.bfReserved2 = 0;
	if (fwrite((void *)&FileHeader, 1, sizeof(FileHeader), fp) != sizeof(FileHeader)) Suc = false;
	// Fill the ImgHeader
	BmpHeader.biSize = 40;
	BmpHeader.biWidth = width;
	BmpHeader.biHeight = height;
	BmpHeader.biPlanes = 1;
	BmpHeader.biBitCount = 8;
	BmpHeader.biCompression = 0;
	BmpHeader.biSizeImage = 0;
	BmpHeader.biXPelsPerMeter = 0;
	BmpHeader.biYPelsPerMeter = 0;
	BmpHeader.biClrUsed = 0;
	BmpHeader.biClrImportant = 0;
	if (fwrite((void *)&BmpHeader, 1, sizeof(BmpHeader), fp) != sizeof(BmpHeader)) Suc = false;
	// write Pallete

	// 根据mod预设颜色
	BYTE tr = -1, tb = -1, tg = -1;
	if (mod == 'r') tb = 0, tg = 0;
	else if (mod == 'g') tr = 0, tb = 0;
	else if (mod == 'b') tr = 0, tg = 0;
	if (mod != 'k')
	{
	for (i = 0; i < 256; i++)
	{
		p[3] = 0;
		p[0] = i & tb;
		p[1] = i & tg;
		p[2] = i & tr; //blue,green,red
		if (fwrite((void *)p, 1, 4, fp) != 4) { Suc = false; break; }
	}
	}
	else
	{
		for (i = 0; i < 256; i++)
		{
			p[3] = 0;
			p[0] = 255 - i;
			p[1] = i;
			p[2] = i; //blue,green,red
			if (fwrite((void *)p, 1, 4, fp) != 4) { Suc = false; break; }
		}
	}

	// write image data
	extend = (width + 3) / 4 * 4 - width; //每行字节个数需要按4的倍数对齐
	if (extend == 0)
	{
		for (pCur = pImg + (height - 1)*width; pCur >= pImg; pCur -= width)
		{
			if (fwrite((void *)pCur, 1, width, fp) != (unsigned int)width) Suc = false; //真实的数据
		}
	}
	else
	{
		for (pCur = pImg + (height - 1)*width; pCur >= pImg; pCur -= width)
		{
			if (fwrite((void *)pCur, 1, width, fp) != (unsigned int)width) Suc = false; //真实的数据
			for (i = 0; i < extend; i++) //每行按4字节对齐进行扩充
			{
				if (fwrite((void *)(pCur + width - 1), 1, 1, fp) != 1) Suc = false;
			}
		}
	}
	// return;
	fclose(fp);
	if (channel == 3)
	{
		delete pImg;
		pImg = temp_save;
	}

	return Suc;
}

bool bmpConverter::Img224bitBmp(const char * DstFile)
{
	//BmpHeader记录的真实的宽度
//当每行字节个数不是4的倍数时,需要进行4对齐
	FILE *fp;
	bool Suc = true;
	int i, extend, w = channel * width;
	BYTE *pCur;
	// Open File
	if (fopen_s(&fp, DstFile, "w+b")) { return false; }
	// Fill the FileHeader
	FileHeader.bfType = ((WORD)('M' << 8) | 'B');
	FileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
	FileHeader.bfSize = FileHeader.bfOffBits + width * height * 3L;
	FileHeader.bfReserved1 = 0;
	FileHeader.bfReserved2 = 0;
	if (fwrite((void *)&FileHeader, 1, sizeof(BITMAPFILEHEADER), fp) != sizeof(BITMAPFILEHEADER)) Suc = false;
	// Fill the ImgHeader
	BmpHeader.biSize = 40;
	BmpHeader.biPlanes = 1;
	BmpHeader.biCompression = 0;
	BmpHeader.biSizeImage = width * height * channel;
	BmpHeader.biXPelsPerMeter = 0;
	BmpHeader.biYPelsPerMeter = 0;
	BmpHeader.biClrUsed = 0;
	BmpHeader.biClrImportant = 0;
	if (fwrite((void *)&BmpHeader, 1, sizeof(BITMAPINFOHEADER), fp) != sizeof(BITMAPINFOHEADER)) Suc = false;
	// write image data

	extend = ((w + 3) / 4 * 4) - w; //每行字节个数需要按4的倍数对齐
	if (!extend)
	{
		for (pCur = pImg + (height - 1) * w; pCur >= pImg; pCur -= w)
		{
			if (fwrite((void *)pCur, 1, w, fp) != (unsigned int)(w)) Suc = false; //真实的数据
		}
	}
	else
	{
		for (pCur = pImg + (height - 1) * w; pCur >= pImg; pCur -= w)
		{
			if (fwrite((void *)pCur, 1, w, fp) != (unsigned int)(w)) Suc = false; //真实的数据
			for (i = 0; i < extend; i++) //扩充的数据
			{
				if (fwrite((void *)(pCur + w - 3 + 0), 1, 1, fp) != 1) Suc = false;
			}
		}
	}
	// return;
	fclose(fp);
	if (Suc)printf("%s 保存成功", DstFile);
	return Suc;
}

3. 在www.onsemi.com网站,寻找2款分别是全局曝光和滚动曝光的图像传感器,给出它们的型号, 并比较它们的帧率、像素数、像元尺寸、靶面大小、感光曲线和最低工作温度等方面的差异。

全局曝光

NOIV1SN025KA

VITA 25K Image Sensor

• 帧率53 Frames per Second (fps) at Full Resolution

• 分辨率 5120 x 5120 Active Pixels

•像元尺寸 4.5 m x 4.5 m Square Pixels

• 靶面打下 35 mm Optical Format

• 操作温度 Operational Range: −40°C to +85°C

感光曲线

image-20210515175924443

滚动曝光

NOIM1SM9600A,

NOIM2SM9600A

• 9.6 MegaPixel Resolution in 3840 × 2500 Format

• 2.4 m × 2.4 m Square Pixels (Shared 4T Pixel Architecture)

• 2/3 inch Optical Format

• 0°C to 70°C Operational Temperature Range

• 20 Frames per Second (fps) at Full Resolution

感光曲线

image-20210515175850991

4. 在www.jai.com网站,寻找2款不同计算机接口、不同分辨率、不同光谱数、不同镜头卡口的摄像机,给出它们的型号,并比较它们的帧率、分辨率、曝光方式、重量与体积、工作温度范围、应用领域等方面的差异。

Wave Series

WA-1000D-CL

短波红外(SWIR)光谱同时双波段成像

2 x 1024 pixel resolution in two 短波红外bands: 900-1400 nm and 1400-1700 nm.

线扫描率 : 39 kHz (39,230 line/second)

接口: camera Link

体积 (H x W x D) 90 mm x 90 mm x 117 mm

(without connector and lens mount protrusion)

重量 910 g

操作温度 -5oC to +45oC

传感器灵敏度 280nV/e- (conversion gain)

传感器宽度 width 25.6 mm

可编程曝光时间 20.38 μs to 1.995ms in 149.9ns increments

输出信号 Camera Link:

LVAL - DVAL - EEN

Hirose 12-pin: XEEN

高分子塑料分类

AP-3200T-10GE

3.2 megapixel CMOS prism area scan

Sensor 1/1.8” 3-CMOS global shutter (IMX252)

帧率, full frame 106 frames/sec. @ 8-bit

体积 (H x W x L) 62 mm x 62 mm x 86.5 mm (excl. connectors)

重量t 270 g

操作温度. (ambient) -5°C to +45°C (20 to 80% non-condensing)

存储温度. (ambient) -25°C to +60°C (20 to 80% non condensing)

视屏信号 output 8/10/12-bits per channel(24/30/36-bit RGB)

视频模式 Normal, Single ROI, Multi ROI, Seq

一台同时呈现彩色和近红外(NIR)图像的棱镜相机,这使得同时在可见光区域进行检测,又通过单个NIR波段或者两个NIR波段组合时的光谱特性来分析材料与缺陷,变得简单可行。这样可以同时检验表面特性和次表面缺陷。支持向下兼容的10GigE接口提供了良好的数据传输速度和网络灵活性。

5. 网上学习一下Sony偏振光图像传感器的成像效果,通过分析来说明偏振光在机器视觉中的应用优点。

在机器视觉中,有图像采集,图像处理两个步骤,对于Sony偏振光图像传感器,它能够

输出灰度与颜色信息,还能够输出偏振度的信息,对于图像采集来说,可以采集到更多的信息,对于图像处理来说,相当于对于图像做了一定的预处理。

6. 寻找一款带液体镜头的远心镜头,写出厂商、型号和接口方式、分辨力、工作距离、景深等核心技术指标。

image-20210515175414777MercuryTL™ 可调焦液态远心镜头

工作距离 (mm):169 - 265

FOV @ Max Sensor Format, H x V (mm):41.2 x 30.9

主要放大倍率 PMAG:0.15X

重量(g):405

水平视场, 1/3” 传感器:30.9mm

水平视场, 1/2” 传感器:41.2mm

孔径 (f/#):f/10

最大传感器格式 :1/2”

7. 寻找一款最低价A4幅面馈纸式双面扫描仪,看其是否支持A3幅面的文档扫描,写出其厂商、型号、核心技术指标和价格。

爱普生/EPSON DS-76

产品类型馈纸扫描方式,一次通过双面扫描

光电元件CMOS CIS

像素深度24 位

光学分辨率600dpi

最大输出分辨率1200dpi

光源RGB LED

扫描速度200dpi/300dpi, 彩色\ 灰度\ 黑白:45ppm/90ipm

文档尺寸最大:215.9mm × 355.6 mm最小:52mm × 50.8mm

( 长纸尺寸:宽:215.9mm / 长:3048mm)

最大纸张尺寸A3(对折直接扫描)

最长纸张尺寸3048mm

纸张厚度40~210 g/m2127~210 g/m2

(A8 paper)~1.5mm (PL card)

8.用手机拍摄一些静止目标和运动目标的图像,并分析它们是否发生了几何扭曲和运动模糊。

   
4FB15945CDBFF5CFF8B6F2402FEEE66F 894AA46CFE944A5C8FBE1AB35416EDA5

有运动模糊手指的轮廓很不清楚

有几何扭曲,因为手指指尖的部分靠近图片顶端,而手指的长度同正常相比显得特别长,而且弯曲

9. 高速公路(路面缺陷)检测车是一种机器视觉应用,它在国内的发展从2001年开始至今经过了两代,第 一代见图片H0103.bmp,第二代见图片H0104.bmp。在第一代中采用了面阵摄像机拍摄路面图像的方式, 在车后架设1个摄像机,摄像机距离路面2m,要求摄像机所拍摄的图像必须覆盖1个约4m宽的车道,且图像 上能够辨认宽度2mm左右的路面裂缝,车辆的最大行驶速度是72Km/h。请问:

**(1) 假设摄像机靶面的宽高比为4:3时,那么摄像机的图像传感器至少应该是多少万像素? **

(4 / 2 * 1e3) * (3 / 2 * 1e3) = 0.3千万像素

(2) 摄像机镜头的视角应该是多少?假设2.8mm焦距的镜头的视角约89度,25mm焦距的镜头约44度,应该选用哪种焦距的镜头?

\[\theta = 2 *arctan(2 / 2) = 90^o\]

所以应选择2.8mm的镜头

(3) 应该每秒钟拍摄几幅图像,才能保证所拍摄的图像序列能够覆盖车行驶过的路面? \(\begin{align} &车速 = 20m/s\\ &图像数 = 车速 / 3 \approx7幅 \end{align}\) **(4) 选择何种曝光方式的摄像机和设置曝光时间为多少微秒,才能保证所拍摄的图像不产生运动模糊? ** \(\begin{align} &0.2mm 一个像素, 车速20m/s\\ &曝光时间 \le 2 * 10^{-3} / 20 = 1 \times10^{-5}s = 100\mu s \end{align}\) **(5) 如果把拍摄的图像原始数据实时存入硬盘,请问硬盘的写盘速度是每秒钟多少兆字节? ** \(\begin{align} 1秒\space7张24bitRGB图,大小=7\times0.3\times10^{7}\times3B = 63MB/s \end{align}\) **(6) 通过上述(1)到(5),说明在设计图像采集系统时尤其需要注意的几个问题。 **

  • 摄像机像素选择要合适,保证能够找到裂纹
  • 摄像机的视角要合适,保证能拍满路面
  • 摄像机的曝光时间短,否则会产生运动模糊
  • 银盘的读写要快,否则无法及时存储相应的图像

(7) 第二代的高速公路检测车的图像采集是如何实现的?请为其选择一款合适的线阵列摄像机和一款合适的激光线结构光照明,给出核心技术指标和计算依据。

使用激光器进行照明,通过车辙摄像机进行图像的采集,输入到计算机中。

线扫描摄像机_ML-HM-16K20H-00-R

hw1_4

波利光电3D结构光模块

hw1_3

摄像机

  • SW-8000M-PMCL

  • 系统 CMOS line scan sensor Sensors type JAI custom made sensor (APS-C)

  • 分辨率 (effective pixels) 8192 pixels horizontal
  • 扫描速度 (max) 99.9 kHz (Full Camera Link 8-bit config.)

  • 操作温度 -5°C to +45°C 存储温度 -25°C to +60°C

10.看懂P54,P55和P67,P68页中的技术参数。

11.图片H0105Gry.bmp是银行点钞机、ATM、清分机中普遍使用的CIS传感器扫描得到的真实图像,从左向右、从上向下分别得到了14个子图。验钞模块一般使用2根CIS(扫描范围:183mm),拍摄正反双面的图 像,面向不同的检测特征,为了减小数据量和降低A/D采样器的频率,采用了变分辨率采集的策略。

**(1) 请分析说明每个子图是使用何种光谱的光、是采用透射光还是反射光得到的。 **

   
image-20210511173814210 白光透射
image-20210511174056097 白光透射
image-20210511174137046 红外反射
image-20210511175029378 红外透射
image-20210511175037445 红外透射
image-20210511175044604 白光透射
image-20210511175049819 白光反射
image-20210511175055321 紫外透射
image-20210511175103578 白光反射
image-20210511175118198 白光反射
image-20210511175157588 白光反射
image-20210511175205567 白光反射
image-20210511175219852 紫外反射
image-20210511175232145 紫外反射

(2) 如果子图(1)的水平分辨率是200dpi、垂直分辨率是130dpi的,那么其他子图(2)~(14)的水平分辨率和 垂直分辨率是多少?

200dpi, 130dpi

(3) 考虑到钱币有时是倾斜的,这时图像的高度就会变大,设定系统容忍的最大倾斜度是10度;考虑到发 现假钞时,需要留出至少20ms剔除假钞的动作时间,所以下一张人民币开始采集的时间必须距离上一 张人民币采集结束的时间隔开20ms;如果图片子图(1)的垂直分辨率是130dpi的,那么CIS的扫描速度 是每行多少us才能保证每分钟900张人民币的鉴别速度? \(每张最长时间=1/ (900/60) = 1/15 s\\ 水平分辨率 200dpi,倾斜后的高度:h = 200 \times sin(10^o) + 130\times cos(10^o)\approx 163dpi\\ 扫描速度 = (1/15 * 1000 - 20) / 163 * 1000 = 286.3\)