OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 18048|回复: 41

ov7670摄像头、ov7725摄像头、ov2640摄像头图像二值化讲解(附源码(基于探索者f407)))

  [复制链接]

15

主题

137

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1427
金钱
1427
注册时间
2019-4-22
在线时间
272 小时
发表于 2019-8-23 14:34:53 | 显示全部楼层 |阅读模式

       先讲下二值化原理,就是先将彩色变成灰度,就像以前的黑白电视,只有灰度的变化,没有彩色。而灰度分为256个等级,即0-255(0为黑色,255为白色),每个等级的灰度程度不一样。所以假定设定一个阈值,该阈值为23,这样我们程序设定摄像头所看到的画面中凡是灰度大于23的为白色,小于23的为黑色,这样就实现了二值化。而其中关键的步骤就是如何将彩色转换为灰度用程序的形式表达出来。现在看下图。 1111.jpg
先看第一行代码,这里的代码就是实现了将彩色实现灰度转换,至于原理大家百度了解下就好了,无非就是一个转换公式,大家记住就好。然后后面的两行代码就是我上面所讲,大于阈值为白色,小于阈值为黑色。
       这个就先讲这么多了,确实二值化比较简单,难点其实还是在于对原子哥摄像头例程代码的理解。ov7725、ov7670跟ov2640的代码有点不同,但是还是那样,把原子哥的摄像头代码理解,这些都不是问题。
       如果有什么疑问的,欢迎下方留言,我会及时为大家解答。
       摄像头OV7670二值化.zip (6.98 MB, 下载次数: 908)
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

15

主题

137

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1427
金钱
1427
注册时间
2019-4-22
在线时间
272 小时
 楼主| 发表于 2019-9-5 16:42:31 | 显示全部楼层
真一百一十一 发表于 2019-9-5 08:55
你好,我想问下,楼主那个dma传输的储存器长度为什么要除以4啊?

第一步:最开始的时候我定义了一个 u16 rgb_buf[200][200]的数组,你得看清楚我这里的(u16),也就是两个字节。
第二步:看DCMI_DMA_Init((u32)rgb_buf,sizeof(rgb_buf)/4,DMA_MemoryDataSize_HalfWord,DMA_MemoryInc_Enable);这个函数,我先解释这函数里面参数的含义。       第一个(u32)rgb_buf:它将我前面定义的u16 rgb_buf[200][200]数组强制转化成了(u32)
       第二个sizeof(rgb_buf)/4:它的含义是指第一个参数数组里面的数据长度,它的定义是(u16)
       第三个DMA_MemoryDataSize_HalfWord:它的含义是DMA一次传输半个字长(u16)数据
第三步:我们来计算u16 rgb_buf[200][200]有多少个字节,即200*200*2(一个字节是u8),然后后面强制转化成u32位,这时的字节数即为200*200*4。这时我们发现字节数变多了,但是我们需要的字节数,即数据长度(第二个参数)为200*200*2,也就是最开始定义的u16 rgb_buf[200][200]的数组的长度。然后这时字节数却因为强制转换成u32位而变成200*200*4了,这时咋办呢,当然是先sizeof(rgb_buf)得到此时数组的字节长度,然后sizeof(rgb_buf),即200*200*4/4,这时就为200*200了,有人就问这明明就和我前面说的不一样呀,我前面说的数据长度的200*200*2,但是你们可能忘记我还说过这个参数,即第二个参数是u16位,所以转换成字节数也就还是200*200*2啦。
回复 支持 2 反对 1

使用道具 举报

15

主题

137

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1427
金钱
1427
注册时间
2019-4-22
在线时间
272 小时
 楼主| 发表于 2019-9-16 16:18:22 | 显示全部楼层
杜先生 发表于 2019-9-15 18:03
楼主。为什么那个buf,我改大点他就出错呢

因为ov2640用的是dma传输数据,而dma最多只能传输65535个数据(只是我个人理解,总之不能改大就是这里的原因),只要你数组里面两个值相乘大于65535就会出错,还有就是要注意数组里面的两个值必须是4的倍数。你要改大,就得用双缓冲,就是双dma,而双dma的方法原子后面的例程有。当初我想试着用双缓冲改大数组,但是没成功就没弄了。当然在实际应用上大多数没必要搞那么大的数据,毕竟数组越大单片机处理速度越慢,这样你的图像帧率就会越低。像我一般用,就只用的176*144的
回复 支持 2 反对 0

使用道具 举报

2

主题

17

帖子

0

精华

初级会员

Rank: 2

积分
140
金钱
140
注册时间
2016-3-4
在线时间
14 小时
发表于 2020-7-3 15:51:00 | 显示全部楼层
非常不错的分享
回复 支持 1 反对 0

使用道具 举报

4

主题

231

帖子

0

精华

高级会员

Rank: 4

积分
755
金钱
755
注册时间
2018-12-7
在线时间
131 小时
发表于 2019-8-23 14:55:13 | 显示全部楼层
多谢分享
回复 支持 反对

使用道具 举报

0

主题

2

帖子

0

精华

新手上路

积分
21
金钱
21
注册时间
2019-6-19
在线时间
5 小时
发表于 2019-8-26 09:34:34 | 显示全部楼层
本帖最后由 qq785407047 于 2019-8-26 10:31 编辑

我想问一下   u32 *dcmi_line_buf[2];//RGB屏时,摄像头采用一行一行读取,定义行缓存     这个指针数组 是这样保存了数据的吗
*dcmi_line_buf[0]第1行一个像素
*dcmi_line_buf[1]第1行二个像素
*(dcmi_line_buf[0]+1)第1行三个像素
*(dcmi_line_buf[1]+1)第1行四个像素。。。。。。。。。。。。。。。
*(dcmi_line_buf[0]+n-1)第1行倒数第二个个像素
*(dcmi_line_buf[1]+n)第1行最后一个个像素


*dcmi_line_buf[0]第2行一个像素
*dcmi_line_buf[1]第2行二个像素
。。。。。。。。。



回复 支持 反对

使用道具 举报

15

主题

137

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1427
金钱
1427
注册时间
2019-4-22
在线时间
272 小时
 楼主| 发表于 2019-8-26 11:20:17 | 显示全部楼层
qq785407047 发表于 2019-8-26 09:34
我想问一下   u32 *dcmi_line_buf[2];//RGB屏时,摄像头采用一行一行读取,定义行缓存     这个指针数组 是这 ...

emmmm,这似乎不是我文件里面的代码吧,这样的话我也不是很清楚
回复 支持 反对

使用道具 举报

0

主题

7

帖子

0

精华

新手上路

积分
44
金钱
44
注册时间
2019-8-31
在线时间
13 小时
发表于 2019-9-5 08:54:24 | 显示全部楼层
你好,我想问一下,楼主那个dma传输的储存器长度为什么要除以4啊?
回复 支持 反对

使用道具 举报

0

主题

7

帖子

0

精华

新手上路

积分
44
金钱
44
注册时间
2019-8-31
在线时间
13 小时
发表于 2019-9-5 08:55:26 | 显示全部楼层
你好,我想问下,楼主那个dma传输的储存器长度为什么要除以4啊?
回复 支持 反对

使用道具 举报

0

主题

7

帖子

0

精华

新手上路

积分
44
金钱
44
注册时间
2019-8-31
在线时间
13 小时
发表于 2019-9-5 16:16:26 | 显示全部楼层
请问下楼主的dma中初始化的储存器宽度为什么要除以4啊?
回复 支持 反对

使用道具 举报

0

主题

7

帖子

0

精华

新手上路

积分
44
金钱
44
注册时间
2019-8-31
在线时间
13 小时
发表于 2019-9-9 09:29:31 | 显示全部楼层
1209943162 发表于 2019-9-5 16:42
第一步:最开始的时候我定义了一个 u16 rgb_buf[200][200]的数组,你得看清楚我这里的(u16),也就是两 ...

嗯,非常感谢解惑
回复 支持 反对

使用道具 举报

0

主题

4

帖子

0

精华

新手入门

积分
11
金钱
11
注册时间
2019-9-4
在线时间
3 小时
发表于 2019-9-11 14:24:09 | 显示全部楼层
这些资料我看看啊,谢谢
回复 支持 反对

使用道具 举报

15

主题

137

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1427
金钱
1427
注册时间
2019-4-22
在线时间
272 小时
 楼主| 发表于 2019-9-11 16:28:51 | 显示全部楼层
yinlinfeng 发表于 2019-9-11 14:24
这些资料我看看啊,谢谢

啥资料  0.0
回复 支持 反对

使用道具 举报

0

主题

3

帖子

0

精华

新手上路

积分
40
金钱
40
注册时间
2019-6-2
在线时间
15 小时
发表于 2019-9-13 16:16:48 | 显示全部楼层
1209943162 发表于 2019-9-5 16:42
第一步:最开始的时候我定义了一个 u16 rgb_buf[200][200]的数组,你得看清楚我这里的(u16),也就是两 ...

强制类型转换应该没有改变数组的数据类型啊
回复 支持 反对

使用道具 举报

2

主题

474

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
6084
金钱
6084
注册时间
2018-6-27
在线时间
524 小时
发表于 2019-9-13 16:30:56 | 显示全部楼层
谢谢分享,学习学习。
回复 支持 反对

使用道具 举报

15

主题

137

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1427
金钱
1427
注册时间
2019-4-22
在线时间
272 小时
 楼主| 发表于 2019-9-14 10:37:21 | 显示全部楼层
玉米地里看过戏 发表于 2019-9-13 16:16
强制类型转换应该没有改变数组的数据类型啊

但是事实上就是把(u16)强制转换为了(u32),不信你自己转换后再用sizeof()函数去打印这个数组的大小
回复 支持 反对

使用道具 举报

10

主题

293

帖子

0

精华

高级会员

Rank: 4

积分
623
金钱
623
注册时间
2019-6-3
在线时间
107 小时
发表于 2019-9-14 10:39:59 | 显示全部楼层
谢谢分享,学习学习。
回复 支持 反对

使用道具 举报

1

主题

7

帖子

0

精华

初级会员

Rank: 2

积分
117
金钱
117
注册时间
2019-7-8
在线时间
27 小时
发表于 2019-9-15 18:03:47 | 显示全部楼层
楼主。为什么那个buf,我改大点他就出错呢
回复 支持 反对

使用道具 举报

15

主题

137

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1427
金钱
1427
注册时间
2019-4-22
在线时间
272 小时
 楼主| 发表于 2019-9-25 21:43:48 | 显示全部楼层
杜先生 发表于 2019-9-15 18:03
楼主。为什么那个buf,我改大点他就出错呢

额,不好意思,其实我很早就回复你了,但今天才发现居然没有回复成功。就是你那个buf数组的两个值相乘不能大于65535,因为DMA最大的传输数据量就是65535。所以当你数组大于这个值后就会显示不正常。你想大点也有办法实现,就是DMA双缓冲,前提你那个板子有两个DMA。至于双缓冲的方法原子在照相机那节视频讲的有。但是我当初看了后,想用双缓冲的方法来增大数组没成功就没弄了。如果你是以学习的态度可以却试试怎么用DMA双缓冲,但如果只是应用的话,没必要把数组搞那么大,数组越大单片机处理速度就会越慢,帧率就会越低。像我当初做板球时,也就只用了176*144的数组。
回复 支持 反对

使用道具 举报

0

主题

1

帖子

0

精华

新手入门

积分
3
金钱
3
注册时间
2019-10-2
在线时间
0 小时
发表于 2019-10-5 16:20:51 | 显示全部楼层
我来看看怎么样 先赞以下
回复 支持 反对

使用道具 举报

0

主题

61

帖子

0

精华

初级会员

Rank: 2

积分
131
金钱
131
注册时间
2019-9-24
在线时间
33 小时
发表于 2019-12-11 15:42:41 | 显示全部楼层
zan            
回复 支持 反对

使用道具 举报

1

主题

232

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3312
金钱
3312
注册时间
2015-4-19
在线时间
364 小时
发表于 2020-5-24 11:10:45 | 显示全部楼层
谢谢分享!
回复 支持 反对

使用道具 举报

14

主题

140

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
1108
金钱
1108
注册时间
2015-12-20
在线时间
118 小时
发表于 2020-5-26 11:50:16 | 显示全部楼层
谢谢楼主精彩的教程,我慢慢消化。
回复 支持 反对

使用道具 举报

1

主题

4

帖子

0

精华

新手上路

积分
29
金钱
29
注册时间
2020-6-15
在线时间
6 小时
发表于 2020-6-17 11:05:23 | 显示全部楼层
非常不错的分享,先试验一下
回复 支持 反对

使用道具 举报

0

主题

1

帖子

0

精华

新手上路

积分
43
金钱
43
注册时间
2019-9-25
在线时间
18 小时
发表于 2020-7-5 10:51:44 | 显示全部楼层
                                for(i=0;i<B;i++)
            {
                for(j=0;j<A;j++)
                {
                    if(j==(A-1))
                    {
                        hang++;
                        LCD_SetCursor(0,i+1);  
                        LCD_WriteRAM_Prepare();                //&#191;aê&#188;D′è&#235;GRAM
                    }
                                                                        //        LCD->LCD_RAM=rgb_buf[i][j];
                                                                                gray=((rgb_buf[i][j]>>11)*19595+((rgb_buf[i][j]>>5)&0x3f)*38469 +(rgb_buf[i][j]&0x1f)*7472)>>16;
                    if(gray<=MAX_threshold&&gray>=MIN_threshold)                                   //&#213;aà&#239;ê&#199;í&#188;&#207;&#241;oú°×&#182;t&#214;μ&#187;ˉ
                    {
                                                                                        num++;
                                                                                        Y_SUM+=i;
                                                                                        X_SUM+=j;
                                                                                        LCD->LCD_RAM=WHITE;
                    }
                    else
                    {
                                                                                        LCD->LCD_RAM=BLACK;
                    }

                }
            }
                                               
                                               
                                               
                X=(X_SUM)/num;Y=(Y_SUM)/num;       
                LCD_Draw_Circle(X,Y,10);
                LCD_DrawLine(X,Y-10,X,Y+10);
                LCD_DrawLine(X-10,Y,X+10,Y);
                LCD_ShowNum(0,240,X,8,16);
                LCD_ShowNum(0,255,Y,8,16);
                LCD_ShowNum(0,270,MIN_threshold,8,16);
                LCD_ShowNum(0,285,MAX_threshold,8,16);               
                X_SUM=0;Y_SUM=0;num=0;       
楼主你能看看我这把坐标求出来的方法对吗?
回复 支持 反对

使用道具 举报

1

主题

25

帖子

0

精华

新手上路

积分
40
金钱
40
注册时间
2020-12-9
在线时间
8 小时
发表于 2020-12-21 16:28:59 | 显示全部楼层
ganghaoxuyao
回复 支持 反对

使用道具 举报

0

主题

4

帖子

0

精华

新手入门

积分
14
金钱
14
注册时间
2020-8-23
在线时间
2 小时
发表于 2021-1-13 15:02:36 | 显示全部楼层
标记一下
回复 支持 反对

使用道具 举报

0

主题

7

帖子

0

精华

新手入门

积分
13
金钱
13
注册时间
2019-11-23
在线时间
4 小时
发表于 2021-1-28 16:14:36 | 显示全部楼层
感谢LZ分享66666
回复 支持 反对

使用道具 举报

0

主题

7

帖子

0

精华

初级会员

Rank: 2

积分
152
金钱
152
注册时间
2021-3-15
在线时间
43 小时
发表于 2021-4-8 16:27:00 | 显示全部楼层
6666标记一下
回复 支持 反对

使用道具 举报

2

主题

40

帖子

0

精华

初级会员

Rank: 2

积分
99
金钱
99
注册时间
2021-5-15
在线时间
14 小时
发表于 2021-5-15 11:37:20 | 显示全部楼层
如果给精英版或者战舰版用要怎么改?
回复 支持 反对

使用道具 举报

2

主题

40

帖子

0

精华

初级会员

Rank: 2

积分
99
金钱
99
注册时间
2021-5-15
在线时间
14 小时
发表于 2021-5-21 14:34:53 | 显示全部楼层
请问你在正点原子原摄像头程序的基础上都改了哪里?只有主函数改了吗?主函数里行数差了好多。小白求指导!!!
回复 支持 反对

使用道具 举报

2

主题

40

帖子

0

精华

初级会员

Rank: 2

积分
99
金钱
99
注册时间
2021-5-15
在线时间
14 小时
发表于 2021-5-22 00:21:47 | 显示全部楼层
请问ov7725能配置直接输出灰度图像吗???
回复 支持 反对

使用道具 举报

2

主题

40

帖子

0

精华

初级会员

Rank: 2

积分
99
金钱
99
注册时间
2021-5-15
在线时间
14 小时
发表于 2021-5-22 00:22:37 | 显示全部楼层
请问ov7725能通过配置,让他直接输出灰度图像吗???
回复 支持 反对

使用道具 举报

0

主题

4

帖子

0

精华

初级会员

Rank: 2

积分
132
金钱
132
注册时间
2021-5-25
在线时间
16 小时
发表于 2021-6-23 16:47:25 | 显示全部楼层
很有帮助,好好学习哈
回复 支持 反对

使用道具 举报

0

主题

13

帖子

0

精华

新手上路

积分
31
金钱
31
注册时间
2021-7-19
在线时间
9 小时
发表于 2021-7-19 15:17:32 | 显示全部楼层
1209943162 发表于 2019-9-5 16:42
第一步:最开始的时候我定义了一个 u16 rgb_buf[200][200]的数组,你得看清楚我这里的(u16),也就是两 ...

是OV2640
回复 支持 反对

使用道具 举报

0

主题

13

帖子

0

精华

新手上路

积分
31
金钱
31
注册时间
2021-7-19
在线时间
9 小时
发表于 2021-7-20 21:11:00 | 显示全部楼层
二值化用于什么地方
回复 支持 反对

使用道具 举报

0

主题

5

帖子

0

精华

新手上路

积分
24
金钱
24
注册时间
2022-4-6
在线时间
7 小时
发表于 2022-4-11 15:22:50 | 显示全部楼层
感觉很不错啊

回复 支持 反对

使用道具 举报

0

主题

8

帖子

0

精华

初级会员

Rank: 2

积分
67
金钱
67
注册时间
2022-4-11
在线时间
5 小时
发表于 2022-4-13 12:57:11 | 显示全部楼层
感谢分享
回复 支持 反对

使用道具 举报

2

主题

10

帖子

0

精华

新手入门

积分
10
金钱
10
注册时间
2023-6-28
在线时间
11 小时
发表于 2023-7-2 11:49:07 | 显示全部楼层
为什么我用stm32f407最小系统板下载ov2640的程序结果没有反应呢
回复 支持 反对

使用道具 举报

15

主题

137

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1427
金钱
1427
注册时间
2019-4-22
在线时间
272 小时
 楼主| 发表于 2023-7-11 20:00:01 | 显示全部楼层
针尾鸭 发表于 2023-7-2 11:49
为什么我用stm32f407最小系统板下载ov2640的程序结果没有反应呢

我当初这份代码是针对老版本的开发板程序,也许现在有新版本了,又或者摄像头有一定的改动,所以就可能会出现不适配的情况了
回复 支持 反对

使用道具 举报

2

主题

14

帖子

0

精华

初级会员

Rank: 2

积分
60
金钱
60
注册时间
2022-12-19
在线时间
7 小时
发表于 2023-9-20 12:31:28 | 显示全部楼层
感谢博主分享,正在学习,刚好需要
回复 支持 反对

使用道具 举报

1

主题

4

帖子

0

精华

新手入门

积分
18
金钱
18
注册时间
2024-4-3
在线时间
5 小时
发表于 2024-4-11 15:58:43 | 显示全部楼层
如何调节这个开窗大小,比如我要400*400的,A=400,B=400,那个buf需要改吗?我把buf也改成【400】【400】,并对下面的函数中存储器长度改了让他不超过65535,编译后报错了。我是新手小白
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-24 16:21

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表