关于opencv中 cvCvtColor函数的问题

LONG5555LONG 2011-09-07 06:25:39
想利用cvCvtColor 把一个RGB图像转换到Lab 空间 为什么转换完了。两幅图片不一样?怎样解决? 求高手指点!积分全部送上了.......
...全文
490 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
Lyn1993 2012-08-03
  • 打赏
  • 举报
回复
showImage显示不一样, 一般图像损失不会让你觉得不一样这么严重吧, 是不是你把CV_BGR2...写成了CV_RGB2...
猪的飞想 2012-07-17
  • 打赏
  • 举报
回复
你想正常显示还得转会到BGR
加泰罗尼亚 2011-11-04
  • 打赏
  • 举报
回复
通常都是BGR显示,你现在把颜色空间变了之后当然数值就发生了变化,你可以再转回去看看一样不,应该差不多
yang_xian521 2011-11-02
  • 打赏
  • 举报
回复
不可能一样啊,显示的时候只是按bgr3个分量显示的吧,你可以看一下showimage函数的实现
youwill 2011-10-02
  • 打赏
  • 举报
回复
你则么看不一样,转换的值当然不能一一比,你是指显示的图吗?转换有精度损失,转过去再转回来会有一点不同的。
ChenLee_1 2011-09-07
  • 打赏
  • 举报
回复
从一个颜色空间转换到另外一个颜色空间,两幅图片当然不一样了
(一)问题的提出 接到一个问题问我,用OpenCV将彩色视频转换为灰度视频并存储到本地磁盘的实践失败,之所以无法存储提问人怀疑是视频编码的问题。 (二)问题的分析 1.OpenCV作为一个非常好的辅助编程的东西,应该是经受得住考验的,怀疑是视频编码出问题不靠谱 2.直觉反应是在写入视频的时候,写入的帧图像存储格式和写入器定义的帧图像格式不符,导致内存报错 3.接收源代码发现有一段代码是这么写的: CvVideoWriter *writer = cvCreateVideoWriter( "myvideo.avi", CV_FOURCC('X', 'V', 'I', 'D'), fps, size); 一下子问题症结就找到了。 要转化为灰度,那这段代码里对函数cvCreateVideoWriter()的掌握程度就要体现了,函数cvCreateVideoWriter()有5个输入参数,第5个输入参数is_color=1是在类cvCreateVideoWriter的构造函数默认好的,这段代码没有定义is_color,说明同意is_color=1,那么writer写入器写到磁盘上的视频即为彩色视频,写入的帧图像是三通道的彩色图像,而后面的代码cvWriteFrame( writer, gray_frame );cvCvtColor( bgr_frame,gray_frame, CV_BGR2GRAY )把彩色的bgr_frame帧图像转化为灰度的图像并存储到gray_frame图像实例,于是这个gray_frame就与写入器要求的彩色三通道帧图像不一致,即分析2的直觉:写入的帧图像存储格式和写入器定义的帧图像格式不符,导致内存报错 (三)问题的解决: 1.把代码进行更改,改成: //创建新的视频文件,需要输入视频文件完整路径名,格式,帧率,长宽值,默认是否为彩色值 CvVideoWriter* writer = cvCreateVideoWriter( "6.avi", //存储完整路径 CV_FOURCC('M','J','P','G'), //编码格式 fps,//帧率 size,//长宽值 0//是否为彩色,0为否,默认1为彩色 ); 2.注意到为什么把编码格式写成'M','J','P','G'?因为这个是无压缩的,直接windows操作系统的media player就可以播放了,如果是'X', 'V', 'I', 'D'格式,那多啰嗦,还要下载有编码解码的播放器才能播放,很累。
// XiHua.cpp : 定义控制台应用程序的入口点。 // //基于索引表的图像细化算法 //#include "stdafx.h" #include "highgui.h" #include "cv.h"//包含cvCreateStructuringElementEx();颜色空间转换函数cvCvtColor()需要 //#include "cxcore.h" //#pragma comment(lib, "opencv_core249.lib")//opencv_core249.lib取代cv.lib等---(不懂以后再一一对应) //#pragma comment(lib,"opencv_highgui249.lib") //#pragma comment(lib,"opencv_imgproc249.lib") #include #include //基于索引表的细化细化算法 //功能:对图象进行细化 //参数:lpDIBBits:代表图象的一维数组 // lWidth:图象高度 // lHeight:图象宽度 // 代表图象的一维数组 图象宽度 图象高度 bool ThiningDIBSkeleton(unsigned char* imagedata, int lWidth, int lHeight) { /* unsigned char* imagedata; imagedata = new uchar[sizeof(char) * src->width * src->height](); */ /* deletemark[256]为前人据8领域总结的是否可以被删除的256种情况 不可以删除用0来表示,能被删除的用1来表示 */ unsigned char deletemark[256] = { 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0 };//索引表 //循环变量 //long i; //long j; unsigned char p0, p1, p2, p3, p4, p5, p6, p7; unsigned char *pmid, *vergeMark; // pmid 用来指向二值图像 vergeMark用来指向存放是否为边缘 unsigned char sum; bool bStart = true; //动态创建一个长度为sizeof(char) * src->width * src->height的数组 //并且初始化把数组元素都设置为0 //长度与imagedata长度一样 long lLength; lLength = lWidth * lHeight; //数组长度 unsigned char *pTemp = new uchar[sizeof(unsigned char) * lLength](); // P0 P1 P2 // P7 P3 // P6 P5 P4 while (bStart) { bStart = false; //每次循环pTemp所有元素都置0 memset(pTemp, 0, lLength);//初始化pTemp指向的lLength空间全部初始化为0 /*---------------首先求边缘点----------------*/ pmid = (unsigned char *)imagedata + lWidth + 1; // pmid 用来指向二值图像矩阵的第二行 +1 表示不考虑图像第一行 vergeMark = (unsigned char *)pTemp + lWidth + 1; //pmidtemp用来指向存放是否为边缘 如果是边缘点 则将其设为1 for (int i = 1; i < lHeight - 1; i++) //lHeight -1表示不考虑图像最后一行 第一列 { for (int j = 1; j < lWidth - 1; j++) //lWidth - 1表示不考虑图像最后一列 { //图像已经是01化,如果是0我们不考虑 if (*pmid == 0) { pmid++; vergeMark++; continue; } //如果是1,是我们考虑的点 我们需要对周围8个进行判断是否边缘 p0 = *(pmid - lWidth - 1); p1 = *(pmid - lWidth); // P0 P1 P2 p2 = *(pmid + 1 - lWidth); // P7 P3 p3 = *(pmid + 1); // P6 P5 P4 p4 = *(pmid + lWidth + 1); p5 = *(pmid + lWidth); p6 = *(pmid + lWidth - 1); p7 = *(pmid - 1); //p0--到---p7的值不是0就是1 sum = p0 & p1 & p2 & p3 & p4 & p5 & p6 & p7;//如果是边缘,肯定周围的P0P1P2P3P4P5P6P7 一定至少有一个为0 if (sum == 0) { *vergeMark = 1;// 表记边缘 } pmid++; vergeMark++; } pmid++;//跳过图像最后一列,不考虑 vergeMark++; pmid++;//跳过图像第一列,不考虑 vergeMark++; } /*---------------沿着边缘现在开始删除----------------*/ pmid = (unsigned char *)imagedata + lWidth + 1; vergeMark = (unsigned char *)pTemp + lWidth + 1; for (long i = 1; i < lHeight - 1; i++) // 不考虑图像第一行 第一列 最后一行 最后一列 { for (long j = 1; j < lWidth - 1; j++) { //*vergeMark=0表示这个点不是边缘,即不进行删除 if (*vergeMark == 0) { pmid++; vergeMark++; continue; } //如果是1,是我们考虑的点 我们需要对周围8个进行判断 //判断一个点是否能去掉, 要根据它的八个相邻点的情况来判断 p0 = *(pmid - lWidth - 1); p1 = *(pmid - lWidth); // P0 P1 P2 p2 = *(pmid - lWidth + 1 ); // P7 P3 p3 = *(pmid + 1); // P6 P5 P4 p4 = *(pmid + lWidth + 1); p5 = *(pmid + lWidth); p6 = *(pmid + lWidth - 1); p7 = *(pmid - 1); /*根据它的八个相邻点的情况形成的索引表进行删除操作 * * 经过预处理后得到待细化的图像是0、1二值图像。 * 像素值为1的是需要细化的部分,像素值为0的是背景区域。 * * 基于索引表的算法就是"依据一定的判断依据",所做出的一张表, * 因为一个像素的8个邻域,我们可以用8位二进制表示,共有256可能情况, * 因此,索引表的大小一般为256。 * 根据索引值对应表的位置存0或1, * 当前像素不能删除存为0, * 可以删除存为1。 * * 然后根据要细化的点的八个邻域的在索引表情况查询, * 若表元素是1,则删除该点(改为背景) * 若是0则保留。 * * * ---------------------------------------- * |p7 | p6 | p5 | p4 | p3 | p2 | p1 | p0 |---索引值对应表的位置-----》共有256可能情况 * ---------------------------------------- (位置1)0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0(位置256) */ //此时p0--到---p7的值不是0就是1 p1 *= 2; p2 *= 4; p3 *= 8; p4 *= 16; p5 *= 32; p6 *= 64; p7 *= 128; sum = p0 | p1 | p2 | p3 | p4 | p5 | p6 | p7; // sum = p0 + p1 + p2 + p3 + p4 + p5 + p6 + p7; if (deletemark[sum] == 1)//可以删除 { *pmid = 0; bStart = true; // 表明本次扫描进行了细化 } pmid++; vergeMark++; } pmid++;//跳过图像最后一列,不考虑 vergeMark++; pmid++;//跳过图像第一列,不考虑 vergeMark++; } } //循环结束说明没有可以继续细化的点了,则为细化结束 delete[]pTemp; return true; } int main(int argc, char* argv[]) { //加载原图像 IplImage* src = cvLoadImage("F:\\zhengning\\QtOpencv\\Images\\xihua.PNG", 0); //---------------------------预处理二值化------------------------------------ //对原图像进行二值化 阈值 cvThreshold(src, src, 100, 255, CV_THRESH_BINARY); /* 图像二值化就是将图像上的像素点的灰度值设置为0或255, 也就是将整个图像呈现出明显的黑白效果 CV_THRESH_BINARY 意思为: if src(x,y) > 100 src(x,y)=255 else src(x,y)=-0 原图像由0到255---->0或255 */ cvNamedWindow("s", 0); cvShowImage("s", src); //-----------------------------预处理0/1化------------------------------------- /* 将imagedata指向的与原图像大小一下的数组空间进行0或1赋值 二值图有原来的0或255----->------0或1 */ //动态创建一个长度为sizeof(char) * src->width * src->height的字符数组 //并且初始化把数组元素都设置为0 unsigned char* imagedata; imagedata = new uchar[sizeof(char) * src->width * src->height](); int x, y; for (y = 0; yheight; y++) { /* widthStep表示存储一行像素需要的字节数 偏移到第y行 */ unsigned char* ptr = (unsigned char*)(src->imageData + y*src->widthStep); for (x = 0; xwidth; x++) { /* 判断第y行第x列的元素值是否大于0 大于0时将数组对应的位置元素设置为1 不大于0则设置为0 imagedata数组里面不是0就时1 */ imagedata[y*src->width + x] = ptr[x] > 0 ? 1 : 0; //经过预处理后得到待细化的图像是0、1二值图像。 } } //----------------------------细化----------------------------------------- //经过预处理后得到待细化的图像是0、1二值图像。 //细化一次,和细化多次,由于索引表不变,每次细化效果都一样,想采用多次细化无法消除毛刺 ThiningDIBSkeleton(imagedata, src->width, src->height); //--------------------对细化后的0/1图二值化(0/255)----------------------------- /* 将ptr指向的与原图像大小一下的数组空间进行0或255赋值 */ for (y = 0; yheight; y++) { /* widthStep表示存储一行像素需要的字节数 偏移到第y行 */ unsigned char* ptr = (unsigned char*)(src->imageData + y*src->widthStep); for (x = 0; xwidth; x++) { /* 判断第y行第x列的元素值是否大于0 大于0时将数组对应的位置元素设置为1 不大于0则设置为0 ptr指向的空间的值不是0就是255 也就是细化之后再次变为二值图 */ ptr[x] = imagedata[y*src->width + x]>0 ? 255 : 0; } } //------------------------------------------------------------------------- cvNamedWindow("src", 0); cvShowImage("src", src); cvWaitKey(0); delete[]imagedata; return 0; }

4,447

社区成员

发帖
与我相关
我的任务
社区描述
图形图像/机器视觉
社区管理员
  • 机器视觉
  • 迪菲赫尔曼
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧