widthStep、width

本文详细介绍了图像处理中widthStep的概念及其作用。widthStep指存储一行像素所需的字节数,必须为4的倍数以实现字节对齐,这对于提高图像处理速度至关重要。通过具体例子解释了如何计算一个图像的widthStep。
部署运行你感兴趣的模型镜像
widthStep表示存储一行像素需要的字节数。
widthStep必须是4的倍数,如果8U图像宽度为3,那么widthStep是4,加一个字节补齐。这个图像的一行需要4个字节,只使用前3个,最后一个空在那儿不用。

也就是一个宽3高3的图像的imageData数据大小为4*3=12字节。



Width:是表示图像的每行像素数,
WidthStep:表示存储一行像素需要的字节数。



转自:

http://blog.sina.com.cn/s/blog_4b46937b0100sb1v.html


在OpenCV里边,widthStep必须是4的倍数,从而实现字节对齐,有利于提高运算速度。
如果8U单通道图像宽度为3,那么widthStep是4,加一个字节补齐。这个图像的一行需要4个字节,只使用前3个,最后一个空着。也就是一个宽3高3的图像的imageData数据大小为4*3=12字节。

这个就是图像对齐的概念,widstep一般要>=width,因为图像是严格按照4个字节的对齐,有时候相机样机会有width不规范比如659*494,这里width就是659,而widstep就是660,只有这样iplimage格式封装才会对齐。







您可能感兴趣的与本文相关的镜像

Stable-Diffusion-3.5

Stable-Diffusion-3.5

图片生成
Stable-Diffusion

Stable Diffusion 3.5 (SD 3.5) 是由 Stability AI 推出的新一代文本到图像生成模型,相比 3.0 版本,它提升了图像质量、运行速度和硬件效率

#include <cstdio> #include <cstring> #include <iostream> #include "Windows.h" #include "HCNetSDK.h" #include "PlayM4.h" #include <opencv2\opencv.hpp> #include "cv.h" #include "highgui.h" #include <time.h> #define USECOLOR 1 using namespace std; using namespace std; //-------------------------------------------- int iPicNum=0;//Set channel NO. LONG nPort=-1; HWND hWnd=NULL; void yv12toYUV(char *outYuv, char *inYv12, int width, int height,int widthStep) { int col,row; unsigned int Y,U,V; int tmp; int idx; //printf("widthStep=%d.\n",widthStep); for (row=0; row<height; row++) { idx=row * widthStep; int rowptr=row*width; for (col=0; col<width; col++) { //int colhalf=col>>1; tmp = (row/2)*(width/2)+(col/2); // if((row==1)&&( col>=1400 &&col<=1600)) // { // printf("col=%d,row=%d,width=%d,tmp=%d.\n",col,row,width,tmp); // printf("row*width+col=%d,width*height+width*height/4+tmp=%d,width*height+tmp=%d.\n",row*width+col,width*height+width*height/4+tmp,width*height+tmp); // } Y=(unsigned int) inYv12[row*width+col]; U=(unsigned int) inYv12[width*height+width*height/4+tmp]; V=(unsigned int) inYv12[width*height+tmp]; // if ((col==200)) // { // printf("col=%d,row=%d,width=%d,tmp=%d.\n",col,row,width,tmp); // printf("width*height+width*height/4+tmp=%d.\n",width*height+width*height/4+tmp); // return ; // } if((idx+col*3+2)> (1200 * widthStep)) { //printf("row * widthStep=%d,idx+col*3+2=%d.\n",1200 * widthStep,idx+col*3+2); } outYuv[idx+col*3] = Y; outYuv[idx+col*3+1] = U; outYuv[idx+col*3+2] = V; } } //printf("col=%d,row=%d.\n",col,row); } //解码回调 视频为YUV数据(YV12),音频为PCM数据 void CALLBACK DecCBFun(long nPort,char * pBuf,long nSize,FRAME_INFO * pFrameInfo, long nReserved1,long nReserved2) { long lFrameType = pFrameInfo->nType; if(lFrameType ==T_YV12) { #if USECOLOR //int start = clock(); IplImage* pImgYCrCb = cvCreateImage(cvSize(pFrameInfo->nWidth,pFrameInfo->nHeight), 8, 3);//得到图像的Y分量 yv12toYUV(pImgYCrCb->imageData, pBuf, pFrameInfo->nWidth,pFrameInfo->nHeight,pImgYCrCb->widthStep);//得到全部RGB图像 IplImage* pImg = cvCreateImage(cvSize(pFrameInfo->nWidth,pFrameInfo->nHeight), 8, 3); cvCvtColor(pImgYCrCb,pImg,CV_YCrCb2RGB); //int end = clock(); #else IplImage* pImg = cvCreateImage(cvSize(pFrameInfo->nWidth,pFrameInfo->nHeight), 8, 1); memcpy(pImg->imageData,pBuf,pFrameInfo->nWidth*pFrameInfo->nHeight); #endif //printf("%d\n",end-start); cvShowImage("IPCamera",pImg); cvWaitKey(1); #if USECOLOR cvReleaseImage(&pImgYCrCb); cvReleaseImage(&pImg); #else cvReleaseImage(&pImg); #endif //此时是YV12格式的视频数据,保存在pBuf中,可以fwrite(pBuf,nSize,1,Videofile); //fwrite(pBuf,nSize,1,fp); } /*************** else if (lFrameType ==T_AUDIO16) { //此时是音频数据,数据保存在pBuf中,可以fwrite(pBuf,nSize,1,Audiofile); } else { } *******************/ } ///实时流回调 void CALLBACK fRealDataCallBack(LONG lRealHandle,DWORD dwDataType,BYTE *pBuffer,DWORD dwBufSize,void *pUser) { DWORD dRet; switch (dwDataType) { case NET_DVR_SYSHEAD: //系统头 if (!PlayM4_GetPort(&nPort)) //获取播放库未使用的通道号 { break; } if(dwBufSize > 0) { if (!PlayM4_OpenStream(nPort,pBuffer,dwBufSize,1024*1024)) { dRet=PlayM4_GetLastError(nPort); break; } //设置解码回调函数 只解码不显示 if (!PlayM4_SetDecCallBack(nPort,DecCBFun)) { dRet=PlayM4_GetLastError(nPort); break; } //设置解码回调函数 解码且显示 //if (!PlayM4_SetDecCallBackEx(nPort,DecCBFun,NULL,NULL)) //{ // dRet=PlayM4_GetLastError(nPort); // break; //} //打开视频解码 if (!PlayM4_Play(nPort,hWnd)) { dRet=PlayM4_GetLastError(nPort); break; } //打开音频解码, 需要码流是复合流 if (!PlayM4_PlaySound(nPort)) { dRet=PlayM4_GetLastError(nPort); break; } } break; case NET_DVR_STREAMDATA: //码流数据 if (dwBufSize > 0 && nPort != -1) { BOOL inData=PlayM4_InputData(nPort,pBuffer,dwBufSize); while (!inData) { Sleep(10); inData=PlayM4_InputData(nPort,pBuffer,dwBufSize); OutputDebugString(L"PlayM4_InputData failed \n"); } } break; } } void CALLBACK g_ExceptionCallBack(DWORD dwType, LONG lUserID, LONG lHandle, void *pUser) { char tempbuf[256] = {0}; switch(dwType) { case EXCEPTION_RECONNECT: //预览时重连 printf("----------reconnect--------%d\n", time(NULL)); break; default: break; } } void main() { //--------------------------------------- // 初始化 NET_DVR_Init(); //设置连接时间与重连时间 NET_DVR_SetConnectTime(2000, 1); NET_DVR_SetReconnect(10000, true); //--------------------------------------- // 获取控制台窗口句柄 //HMODULE hKernel32 = GetModuleHandle((LPCWSTR)"kernel32"); //GetConsoleWindow = (PROCGETCONSOLEWINDOW)GetProcAddress(hKernel32,"GetConsoleWindow"); //--------------------------------------- // 注册设备 LONG lUserID; NET_DVR_DEVICEINFO_V30 struDeviceInfo; lUserID = NET_DVR_Login_V30("10.102.7.88", 8000, "admin", "12345", &struDeviceInfo); if (lUserID < 0) { printf("Login error, %d\n", NET_DVR_GetLastError()); NET_DVR_Cleanup(); return; } //--------------------------------------- //设置异常消息回调函数 NET_DVR_SetExceptionCallBack_V30(0, NULL,g_ExceptionCallBack, NULL); //cvNamedWindow("IPCamera"); //--------------------------------------- //启动预览并设置回调数据流 NET_DVR_CLIENTINFO ClientInfo; ClientInfo.lChannel = 1; //Channel number 设备通道号 ClientInfo.hPlayWnd = NULL; //窗口为空,设备SDK不解码只取流 ClientInfo.lLinkMode = 0; //Main Stream ClientInfo.sMultiCastIP = NULL; LONG lRealPlayHandle; lRealPlayHandle = NET_DVR_RealPlay_V30(lUserID,&ClientInfo,fRealDataCallBack,NULL,TRUE); if (lRealPlayHandle<0) { printf("NET_DVR_RealPlay_V30 failed! Error number: %d\n",NET_DVR_GetLastError()); return; } //cvWaitKey(0); Sleep(-1); //fclose(fp); //--------------------------------------- //关闭预览 if(!NET_DVR_StopRealPlay(lRealPlayHandle)) { printf("NET_DVR_StopRealPlay error! Error number: %d\n",NET_DVR_GetLastError()); return; } //注销用户 NET_DVR_Logout(lUserID); NET_DVR_Cleanup(); return; } 转为python语言
06-13
//By wysaid //blog: http://wysaid.org #define _CRT_SECURE_NO_WARNINGS #include <graphics.h> #include <vector> #include <cmath> using namespace std; struct Point { Point() : x(0), y(0), dx(0), dy(0) {} Point(float vx, float vy) : x(vx), y(vy), dx(0), dy(0) {} float x, y; float dx, dy; }; class Net { public: Net() : m_index(0), m_intensity(0.2f), m_lastIndex(-1) {} ~Net() {} bool initNet(int w, int h) { if(w < 2 || h < 2) return false; m_width = w; m_height = h; m_vec[0].resize(w * h); m_vec[1].resize(w * h); float widthStep = 1.0f / (w - 1); float heightStep = 1.0f / (h - 1); for(int i = 0; i != h; ++i) { const float heightI = i * heightStep; int index = w * i; for(int j = 0; j != w; ++j) { const float widthJ = j * widthStep; m_vec[0][index] = Point(widthJ, heightI); m_vec[1][index] = Point(widthJ, heightI); ++index; } } return true; } void update() { const float widthStep = 1.0f / (m_width - 1.0f); const float heightStep = 1.0f / (m_height - 1.0f); int index = (m_index + 1) % 2; for(int i = 1; i < m_height - 1; ++i) { //const float heightI = i * heightStep; const int k = m_width * i; for(int j = 1; j < m_width - 1; ++j) { const int h = k + j; float dx, dy; dx = (m_vec[m_index][h - 1].x + m_vec[m_index][h + 1].x - m_vec[m_index][h].x * 2.0f); dy = (m_vec[m_index][h - 1].y + m_vec[m_index][h + 1].y - m_vec[m_index][h].y * 2.0f); dx += (m_vec[m_index][h - m_width].x + m_vec[m_index][h + m_width].x - m_vec[m_index][h].x * 2.0f); dy += (m_vec[m_index][h - m_width].y + m_vec[m_index][h + m_width].y - m_vec[m_index][h].y * 2.0f); //模拟能量损失, 当加速度方向与速度方向相反时,加快减速 if(((unsigned&)dx >> 31) != ((unsigned&)m_vec[m_index][h].dx >> 31)) dx *= 1.0f + m_intensity; if(((unsigned&)dy >> 31) != ((unsigned&)m_vec[m_index][h].dy >> 31)) dy *= 1.0f + m_intensity; m_vec[m_index][h].dx += dx * m_intensity; m_vec[m_index][h].dy += dy * m_intensity; m_vec[index][h].dx = m_vec[m_index][h].dx; m_vec[index][h].dy = m_vec[m_index][h].dy; m_vec[index][h].x = m_vec[m_index][h].x + m_vec[index][h].dx; m_vec[index][h].y = m_vec[m_index][h].y + m_vec[index][h].dy; } } m_index = index; } void catchPoint(float x, float y) { int index; if(m_lastIndex < 0) { float mdis = 1e9f; for(int i = 1; i < m_height - 1; ++i) { const int k = m_width * i; for(int j = 1; j < m_width - 1; ++j) { const int h = k + j; const float dis = fabsf(x - m_vec[m_index][h].x) + fabsf(y - m_vec[m_index][h].y); if(dis < mdis) { index = h; mdis = dis; } } } m_lastIndex = index; } else index = m_lastIndex; m_vec[0][index].x = x; m_vec[0][index].y = y; m_vec[1][index].x = x; m_vec[1][index].y = y; m_vec[0][index].dx = 0.0f; m_vec[0][index].dy = 0.0f; m_vec[1][index].dx = 0.0f; m_vec[1][index].dy = 0.0f; } void releasePoint() { m_lastIndex = -1; } void drawNet(float width, float height) { auto &v = m_vec[m_index]; for(int i = 0; i != m_height; ++i) { const int k = i * m_width; for(int j = 1; j != m_width; ++j) { const int h = k + j; ege_line(v[h - 1].x * width, v[h - 1].y * height, v[h].x * width, v[h].y * height); } } for(int i = 0; i != m_width; ++i) { for(int j = 1; j != m_height; ++j) { const int h2 = j * m_width + i; const int h1 = (j - 1) * m_width + i; ege_line(v[h1].x * width, v[h1].y * height, v[h2].x * width, v[h2].y * height); } } } void intensityInc(float f) { m_intensity += f; if(m_intensity > 0.3f) m_intensity = 0.3f; } void intensityDec(float f) { m_intensity -= f; if(m_intensity < 0.001f) m_intensity = 0.001f; } float getIntensity() { return m_intensity; } private: vector<Point> m_vec[2]; int m_index; int m_width, m_height; float m_intensity; int m_lastIndex; }; int main() { initgraph(800, 600, INIT_RENDERMANUAL); setcaption("EGE网格 By wysaid"); Net net; char buffer[1024]; sprintf(buffer, "当前网格强度:%g", net.getIntensity()); net.initNet(80, 60); for(; is_run(); delay_fps(60)) { cleardevice(); if(keystate(key_mouse_l)) { int x, y; mousepos(&x, &y); net.catchPoint(x / 800.0f, y / 600.0f); } else net.releasePoint(); if(kbhit()) { switch(getch()) { case '+': net.intensityInc(0.005f); break; case '-': net.intensityDec(0.005f); break; case 27: exit(0); } flushkey(); sprintf(buffer, "当前网格强度:%g", net.getIntensity()); } setcolor(GREEN); net.drawNet(800, 600); net.update(); setcolor(0x00ff0000); outtextxy(10, 10, "按'+'或者'-'可以增大或者减小网格弹力!这个版本由wysaid制作, 参见: http://blog.wysaid.org"); outtextxy(10, 30, buffer); } closegraph(); return 0; }为什么在小熊猫dev3.3.1上D:/Backup/Documents/untitled2.cpp 0 -1 In member function 'void Net::update()': D:/Backup/Documents/untitled2.cpp 55 15 [警告] unused variable 'widthStep' [-Wunused-variable] D:/Backup/Documents/untitled2.cpp 56 15 [警告] unused variable 'heightStep' [-Wunused-variable] D:/Backup/Documents/untitled2.cpp 0 -1 In function 'int main()': D:/Backup/Documents/untitled2.cpp 191 2 [错误] 'sprintf' was not declared in this scope D:/Backup/Documents/untitled2.cpp 8 1 [说明] 'sprintf' is defined in header '<cstdio>'; did you forget to '#include <cstdio>'?
最新发布
08-10
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值