提取图像里面的红色灯笼(一)
图像的分割:RGB空间图像的分割:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | /************************************************************** 函数功能:对图像rgb空间红色灯笼的提取 输入参数:源图像src;目标图像des;图像参数width,height,nChannels; 输出参数:目标图像 **************************************************************/ void rgb_seg(unsigned char * des, const unsigned char * src, int width, int height, int nChannels) { printf ( "%d,%d,%d," ,nChannels,width,height); unsigned char * ocl = new unsigned char [width * height * nChannels]; for ( int y = 0; y < height; y++) { for ( int x = 0; x < width; x++) { int img_B= src[y * width * nChannels + x * nChannels ] ; int img_G= src[y * width * nChannels + x * nChannels + 1] ; int img_R= src[y * width * nChannels + x * nChannels + 2] ; if ((img_R>140)&&(img_G<70)&&(img_B<70)) //简单的阈值提取 for ( int n=0;n<nChannels;n++) des[y * width * nChannels + x * nChannels + n] = src[y * width * nChannels + x * nChannels + n] ; else for ( int n=0;n<nChannels;n++) des[y * width * nChannels + x * nChannels + n] =255; } } ImageDilation(ocl, des, width, height, nChannels,7); //用7*7的模板进行膨胀 ImageErosion(des, ocl, width, height, nChannels,13); //用13*13的模板进行腐蚀 ImageDilation(ocl, des, width, height, nChannels,13); //用13*13的模板进行膨胀 ImageReturn(des,ocl,src, width, height, nChannels,10); //用10*10的模板还原灯笼 } |
下图第一幅为简单的红色分量阈值分割,第二幅为对前一副图像7*7的模板的膨胀。
下图第一幅为用13*13的模板进行腐蚀,第二幅用13*13的模板再次进行膨胀:
可见再次膨胀后的图像消除了所有的噪点,我们对这幅图像进行还原,还原的基本原理就是对图像有红色区域的部分用源图像进行相对应位置的填充。如下所示,对比原图可见其较好的找出了灯笼的轮廓。
图像的分割:HSI空间图像的分割:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | /************************************************************** 函数功能:对图像hsi空间红色灯笼的提取 输入参数:源图像src;目标图像des;图像参数width,height,nChannels; 输出参数:目标图像 **************************************************************/ void hsi_seg(unsigned char * des, const unsigned char * src, int width, int height, int nChannels) { printf ( "%d,%d,%d," ,nChannels,width,height); unsigned char * ocl = new unsigned char [width * height * nChannels]; unsigned char * hsi = new unsigned char [width * height * nChannels]; rgb_hsi(hsi,src, width, height, nChannels); //hsi分量提取 for ( int y = 0; y < height; y++) { for ( int x = 0; x < width; x++) { int img_H= hsi[y * width * nChannels + x * nChannels ] ; int img_S= hsi[y * width * nChannels + x * nChannels + 1] ; int img_I= hsi[y * width * nChannels + x * nChannels + 2] ; if (((img_H<104)&&(img_H>102))&&(img_I>40)&&(img_S>160)) { //printf("%d, ",img_S); for ( int n=0;n<nChannels;n++) des[y * width * nChannels + x * nChannels + n] = src[y * width * nChannels + x * nChannels + n] ; } else for ( int n=0;n<nChannels;n++) des[y * width * nChannels + x * nChannels + n] =255; } } ImageErosion(ocl, des, width, height, nChannels,2); //进行2*2的模板腐蚀 ImageDilation(des, ocl, width, height, nChannels,18); //进行18*18的模板膨胀 memcpy (ocl, des, nChannels*width*height); ImageReturn(des,ocl,src, width, height, nChannels,10); //进行10*10的模板还原 } |
下图第一幅图像为HIS空间对图像进行的简单的阈值分割,分割条件:
((img_H<104)&&(img_H>102))&&(img_I>40)&&(img_S>160)
可见其噪点很少,对其进行2*2的模板腐蚀再进行18*18的模板膨胀,如下右图所示:
可见右图已经比较好的找出了灯笼的位置,我们用进行10*10的模板还原得到下面的图,和原图比较,也得到了比较好的效果。
下面是图像腐蚀、膨胀、还原的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 | /************************************************************** 函数功能:对图像进行M*M模板的腐蚀 输入参数:源图像src;目标图像des;图像参数width,height,nChannels;腐蚀边长M 输出参数:目标图像 **************************************************************/ void ImageErosion(unsigned char * des, const unsigned char * src, int width, int height, int nChannels, int M) { memcpy (des, src, nChannels*width*height); int m,p,k=0,q=0; for ( int y = 20; y < height-20; y++) { for ( int x = 20; x < width-20; x++) { if ((src[y * width * nChannels + x * nChannels + 2]!=255)) { k=k+1; for (m=-M;m<=M;m++) { for (p=-M;p<=M;p++) { if ((src[(y+m) * width * nChannels + (x+p) * nChannels + 2])==255) { for ( int n=0;n<nChannels;n++) des[y * width * nChannels + x * nChannels + n]=255; } } } } else { q=q+1; } } } //printf("E%d %d",k,q); } /************************************************************** 函数功能:对图像进行M*M模板的膨胀 输入参数:源图像src;目标图像des;图像参数width,height,nChannels;膨胀边长M 输出参数:目标图像 **************************************************************/ void ImageDilation(unsigned char * des, const unsigned char * src, int width, int height, int nChannels, int M) { int m,p,k=0,q=0; memcpy (des, src, nChannels*width*height); for ( int y = 20; y < height-20; y++) { for ( int x = 20; x < width-20; x++) { if ((src[y * width * nChannels + x * nChannels + 2]!=255)) { k=k+1; for (m=-M;m<=M;m++) { for (p=-M;p<=M;p++) { for ( int n=0;n<nChannels;n++) des[(y+m) * width * nChannels + (x+p) * nChannels + n]=src[y * width * nChannels + x * nChannels + n]; } } } else { q=q+1; } } } //printf("D%d %d",k,q); } /************************************************************** 函数功能:对图像进行M*M模板的原图像还原 输入参数:源图像src;目标图像des;图像参数width,height,nChannels;还原边长M 输出参数:目标图像 **************************************************************/ void ImageReturn(unsigned char * des, const unsigned char * ocl, const unsigned char * src, int width, int height, int nChannels, int M) { memcpy (des, ocl, nChannels*width*height); int m,p,k=0,q=0; for ( int y = 30; y < height-30; y++) { for ( int x = 30; x < width-30; x++) { if ((ocl[y * width * nChannels + x * nChannels + 2]!=255)) { k=k+1; for (m=-M;m<=M;m++) { for (p=-M;p<=M;p++) { int B= src[(y+m) * width * nChannels + (x+p) * nChannels ] ; int G= src[(y+m) * width * nChannels + (x+p) * nChannels + 1] ; int R= src[(y+m) * width * nChannels + (x+p) * nChannels + 2] ; if (R>130) { for ( int n=0;n<nChannels;n++) des[(y+m) * width * nChannels + (x+p) * nChannels + n]=src[(y+m) * width * nChannels + (x+p) * nChannels + n]; //将还原区域用源图像进行填充 } } } } } } } |
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 理解Rust引用及其生命周期标识(下)
· 从二进制到误差:逐行拆解C语言浮点运算中的4008175468544之谜
· .NET制作智能桌面机器人:结合BotSharp智能体框架开发语音交互
· 软件产品开发中常见的10个问题及处理方法
· .NET 原生驾驭 AI 新基建实战系列:向量数据库的应用与畅想
· 2025成都.NET开发者Connect圆满结束
· Ollama本地部署大模型总结
· langchain0.3教程:从0到1打造一个智能聊天机器人
· 用一种新的分类方法梳理设计模式的脉络
· 在 VS Code 中,一键安装 MCP Server!