山东科威数控机床有限公司铣床官方网站今天是:2025-05-03切换城市[全国]-网站地图
推荐产品 :
推荐新闻
技术文章当前位置:技术文章>

猪肉颜色分级仪的制作方法

时间:2025-05-03    作者: 管理员

专利名称:猪肉颜色分级仪的制作方法
技术领域
本项发明猪肉颜色分级仪,属于计算机视觉和农产品质量自动分级设备领域。
背景技术
生鲜猪肉随冷藏、摆放的时间不同其质量发生显著的变化,一个简单识别的标志性指标就是猪肉的颜色,消费者经常会根据猪肉颜色的差异来选择购买,没有一个科学的、客观的颜色等级标准来参照,同时超市出售的生鲜猪肉没有依据生鲜肉的摆放时间(颜色不同)采用不同的价格,没有真正做到“按质论价”;国外的猪肉质量都有相应的颜色等级标准,他们的猪肉颜色标准在猪肉的定价、国内零售、国际贸易方面起着巨大的作用,而我国猪肉产品至今没有自己的颜色等级标准,无法和国际接轨,参与世界的猪肉贸易竞争,在国外,利用计算机视觉技术对猪肉颜色进行分级已经得到了商品化应用,但国内这方面的技术及设备还是空白。因此迫切需要建立一系列计算机分级系统,统一猪肉颜色等级标准,以适应质量控制和市场的需要。

发明内容
技术问题 本发明针对目前我国缺乏猪肉颜色计算机分级系统,建立了一套猪肉颜色分级仪,以克服传统的猪肉颜色分级主要依靠人的视觉器官进行,容易受到人的主观意志影响,分级的结果缺乏客观性的缺陷。
技术方案 一种猪肉颜色分级仪器,包括图像采集设备和猪肉颜色分级软件,其特征在于 (1)图像获取设备包括图像采集室4、数码相机5 图像采集室4为直径为600mm的半球形耐高温材料制成,内壁涂成白色,4个50W卤素灯1等间距安装于图像采集室4的底部,图像采集室4内的载样台2面为用细砂布打磨过的黑色橡胶板,样品3置于橡胶板上,图像采集室4顶端开一直径为45mm圆孔;选用CANON-PowerShotA70数码相机5,镜头穿过于图像采集室4顶圆孔; (2)猪肉颜色分级软件 猪肉颜色计算机分级软件由图像输入控制模块、图像分割与识别模块、图像颜色特征参数提取模块、猪肉颜色等级输出模块组成 a、图像输入控制模块可以自动打开数码相机5镜头、自动拍摄样品3的彩色图像; b、图像分割与识别模块用于对输入的彩色图像进行去噪、去背景、边缘提取,最终获取猪肉图像的有效特征颜色提取区域; c、图像颜色特征参数提取模块用于对图像分割与识别模块获取的有效颜色提取区域提取图像的颜色特征参数,包括红色R、绿色G、蓝色B、色彩H、饱和度S、亮度V; d、猪肉颜色等级输出模块用于调用猪肉颜色等级模型猪肉颜色等级G=4.62+6.63*S-10.20*V,输出猪肉颜色级别。
有益效果 本发明猪肉颜色分级仪已在南京苏果等超市进行小规模试用,试用后,顾客对该系统反应良好,有了这套系统,他们真切的感受到“按质论级、按级论价”带来的实惠,同时该系统性能稳定、功能齐全、使用方便、操作简单,受到超市管理人员和设备操作人员的好评。


图1猪肉颜色计算机分级设备图像输入系统 ①灯泡②载样台③样品④图像采集室⑤数码相机⑥数据线⑦计算机 图2猪肉颜色计算机分级仪总体框架图 五具体实施例方式 本发明为一套猪肉颜色分级仪,由图像获取设备与猪肉颜色计算机分级软件组成。
(1)图像获取设备 a、图像采集室④由直径为600mm的半球形,内壁涂成白色,4个50W卤素灯等间距安装于图像采集室④的底部,图像采集室④内的载样台②面为用细砂布打磨过的黑色橡胶板,样品③置于橡胶板上,图像采集室④顶端开一直径为45mm圆孔。
b、选用CANNON-PowerShotA70数码相机⑤,镜头穿过于图像采集室④顶圆孔。
c、数码相机⑤与计算机⑦之间采用随数码相机⑤附带的USB2.0数据线⑥连接。
(2)猪肉颜色计算机分级软件 猪肉颜色计算机分级软件由图像输入控制模块、图像分割与识别模块、图像颜色特征参数提取模块、猪肉颜色等级输出模块组成,该软件开发语言为Visual C++6.0。
a、图像输入控制模块结合Canon Digital Camera SDK6.0.1(Canon DC-SDK6.0.1)开发完成,该模块可以自动打开数码相机⑤镜头、自动拍摄样品③的彩色图像。
b、图像分割与识别模块用于对输入的彩色图像进行去噪、去背景、边缘提取,最终获取猪肉图像的有效特征颜色提取区域。
c、图像颜色特征参数提取模块用于对图像分割与识别模块获取的有效颜色提取区域提取图像的颜色特征参数,包括红色R、绿色G、蓝色B、色彩H、饱和度S、亮度V。
d、猪肉颜色等级输出模块用于调用猪肉颜色等级模型(猪肉颜色等级G=4.62+6.63*S-10.20*V),输出猪肉颜色级别,实现了猪肉颜色的分级。
系统软件的安装对系统软硬件的要求是 ●CPU在奔腾II以上内存128MB以上 硬盘20G以上 ●Windows98或以上windows操作系统 通过以上硬件设备和软件作为核心支持,最终实现了猪肉颜色计算机智能分级。附程序原代码 一、图像输入控制模块(控制数码相机) LRESULT CRelCtrlDlg∷WindowProc(UINT message,WPARAM wParam,LPARAM 1Param)  {  ∥TODOAdd your specialized code here and/or call the base class<!-- SIPO <DP n="2"> --><dp n="d2"/>   cdError err;   BOOL fRes;   CProgress CProg;   char szSavePath[MAX_PATH];   cdUInt32 NumData;   if(message==g_ReleaseOnMessage)   {   /*UI is locked so that information may not be changed.*/   err=CDLockUI(m_hSource);   if(GETERRORID(err)!=cdOK)   {   goto camerr;   }   /*It sets up so that a complete message may be disregarded.*/   m_fProgramRelease=TRUE;   /*A special camera ends a view finder.*/   if(m_RelControlCap&amp;cdRELEASE_CONTROL_CAP_ABORT_VIEWFINDER)   {   if(m_fVFEnd)   {   /*A view finder is ended.*/   err=CDTermViewfinder(m_hSource);   if(GETERRORID(err)!=cdOK)   {   goto camerr;   }   /*A thread is ended.*/   m_fVFEnd=FALSE;   g_CpVFThread->ResumeThread();   WaitForSingleObject(g_CpVFThread->m_hThread,INFINITE);   Invalidate();   UpdateWindow();   }   }   /*A photograph is taken.*/   NumData=0;   err=CDRelease(m_hSource,FALSE,NULL,NULL,cdPROG_NO_REPORT,&amp;NumData);   if(GETERRORID(err)!=cdOK)   {   goto camerr;   }   /*The directory to save is acquired.*/<!-- SIPO <DP n="3"> --><dp n="d3"/>  GetSavePath(szSavePath,MAX_PATH);  /*The photoed picture is saved.*/  fRes=CProg.GetReleaseData(m_hSource,NumData,szSavePath,m_fileName);  if(!fRes)  {  goto apierr;  }  else if(GETERRORID(CProg.m_LastErr)==cdOPERATION_CANCELLED)  {  m_fProgramRelease=FALSE;  CDUnlockUI(m_hSource);  returnTRUE;  }  else if(GETERRORID(CProg.m_LastErr)!=cdOK)  {  err=CProg.m LastErr;  goto camerr;  }  /*The lock of UI is canceled.*/  err=CDUnlockUI(m_hSource);  if(GETERRORID(err)!=cdOK)  {  goto camerr;  }  /*It sets up so that a complete message may be received.*/  m_fProgramRelease=FALSE;  returnTRUE;}else if(message==g_ReleaseCompleteMessage){  if(m_fProgramRelease==FALSE)  {  /*UI is locked so that information may not be changed.*/  err=CDLockUI(m_hSource);  if(GETERRORID(err)!=cdOK)  {  goto camerr;  }  /*The directory to save is acquired.*/  GetSavePath(szSavePath,MAX_PATH);  NumData=(cdUInt32)wParam;  /*The photoed picture is saved.*/  fRes=CProg.GetReleaseData(m_hSource,NumData,szSavePath,m_fileName);  if(!fRes)<!-- SIPO <DP n="4"> --><dp n="d4"/>  {  goto apierr;  }  else if(GETERRORID(CProg.m_LastErr)==cdOPERATION_CANCELLED)  {  m_fProgramRelease=FALSE;  CDUnlockUI(m_hSource);  returnTRUE;  }  else if(GETERRORID(CProg.m_LastErr)!=cdOK)  {  err=CProg.m_LastErr;  goto camerr;  }  /*The lock of UI is canceled.*/  err=CDUnlockUI(m_hSource);  if(GETERRORID(err)!=cdOK)  {  goto camerr;  }  returnTRUE;  }}else if(message==g_AbortPCEVF){  if(m_fVFEnd)  {  /*A view finder is ended.*/  err=CDTermViewfinder(m_hSource);  if(GETERRORID(err)!=cdOK)  {  goto camerr;  }  /*A thread is ended.*/  m_fVFEnd=FALSE;  g_CpVFThread->ResumeThread();  WaitForSingleObject(g_CpVFThread->m_hThread,INFINITE);  Invalidate();  UpdateWindow();  }  return TRUE;}<!-- SIPO <DP n="5"> --><dp n="d5"/>return CDialog∷WindowProc(message,wParam,1Param);  camerr  char szErrStr[256];  wsprintf(szErrStr,″ErrorCode=0x%08X″,err);  MessageBox(szErrStr);  CDUnlockUI(m_hSource);  m_fProgramRelease=FALSE;  returnFALSE;apierr  MessageBox(″API Error″);  CDUnlockUI(m_hSource);  m_fProgramRelease=FALSE;  returnFALSE;}void CRelCtrlDlg∷OnDestroy(){  CDialog∷OnDestroy();  ∥TODOAdd your specialized code here and/or call the base class  cdError err;  char szErrStr[256];  /*End processing of CDSDK is performed.*/  err=CDFinishSDK();  if(GETERRORID(err)!=cdOK)  {  wsprintf(szErrStr,″ErrorCode=0x%08X″,err);  MessageBox(szErrStr);  }}void CRelCtrlDlg∷SetPicQuery(){  UpdateData();  cdError err1,err2;  CString CAddStr;  m_CInfoString=″″;  /*Quality of image,image size,and the average size of a picture file are acquired.*/  cdCompQuality Quality;  cdImageSize Size;  ∥ ()  switch(m_Camsize){  case 0   Size=cdIMAGE_SIZE_SMALL;<!-- SIPO <DP n="6"> --><dp n="d6"/>   break;case 1   Size=cdIMAGE_SIZE_MEDIUM1;   break;case 2   Size=cdIMAGE_SIZE_MEDIUM2;   break;case 3   Size=cdIMAGE_SIZE_LARGE;   break;}switch(m_CamQuery){case 0   Quality=cdCOMP_QUALITY_NORMAL;   break;case 1   Quality=cdCOMP_QUALITY_FINE;   break;case 2   Quality=cdCOMP_QUALITY_SUPERFINE;   break;}err1=CDSetImageFormatAttribute(m_hSource,Quality,Size);m_CamMode=17;cdShootingModeShootingMode;switch(m_CamMode){case 0   ShootingMode=cdSHOOTING_MODE_AUTO;   break;case 1   ShootingMode=cdSHOOTING_MODE_PROGRAM;   break;case 2   ShootingMode=cdSHOOTING_MODE_TV;   break;case 3   ShootingMode=cdSHOOTING_MODE_AV;   break;case 4   ShootingMode=cdSHOOTING_MODE_MANUAL;   break;case 5<!-- SIPO <DP n="7"> --><dp n="d7"/>   ShootingMode=cdSHOOTING_MODE_A_DEP;   break;case 6   ShootingMode=cdSHOOTING_MODE_M_DEP;   break;case 7   ShootingMode=cdSHOOTING_MODE_BULB;   break;case 8   ShootingMode=cdSHOOTING_MODE_MANUAL_2;   break;case 9   ShootingMode=cdSHOOTING_MODE_FAR_SCENE;   break;case 10   ShootingMode=cdSHOOTING_MODE_FAST_SHUTTER;   break;case 11   ShootingMode=cdSHOOTING_MODE_SLOW_SHUTTER;   break;case 12   ShootingMode=cdSHOOTING_MODE_NIGHT_SCENE;   break;case 13   ShootingMode=cdSHOOTING_MODE_GRAY_SCALE;   break;case 14   ShootingMode=cdSHOOTING_MODE_SEPIA;   break;case 15   ShootingMode=cdSHOOTING_MODE_PORTRAIT;   break;case 16   ShootingMode=cdSHOOTING_MODE_SPOT;   break;case 17   ShootingMode=cdSHOOTING_MODE_MACRO;   break;case 18   ShootingMode=cdSHOOTING_MODE_BW;   break;case 19   ShootingMode=cdSHOOTING_MODE_PANFOCUS;   break;<!-- SIPO <DP n="8"> --><dp n="d8"/>  case 20   ShootingMode=cdSHOOTING_MODE_VIVID;   break;  case 21   ShootingMode=cdSHOOTING_MODE_NEUTRAL;   break;  case 22   ShootingMode=cdSHOOTING_MODE_INVALID;   break;  }  err2=CDSetShootingMode(m_hSource,ShootingMode);  if(GETERRORID(err1)==cdOK/*&amp;&amp; GETERRORID(err2)==cdOK*/)  GetCameraInformation();  else  MessageBox(″Set Error″);}void CRelCtrlDlg∷SetCamMode(){  cdError err;  err=CDLockUI(m_hSource);  if(GETERRORID(err)!=cdOK)  {  goto camerr;  }  err=SetReleaseState();  if(GETERRORID(err)!=cdOK)  {  goto camerr;  }  /*The lock of UI is canceled.*/  err=CDUnlockUI(m_hSource);  if(GETERRORID(err)!=cdOK)  {  goto camerr;  }  return;<!-- SIPO <DP n="9"> --><dp n="d9"/>camerr.  char szErrStr[256];  wsprintf(szErrStr,″ErrorCode=0x%08X″,err);  MessageBox(szErrStr);  CDUnlockUI(m_hSource);} 二、图像分割与识别模块(-将内存中图像转化为灰度模式)。
BOOL CJiSuan∷ChangtoGrid(){  int w=m_dib.GetDIBWidth();  int h=m_dib.GetDIBHeight();  for(int i=0;i<w;i++)   for(int j=O;j<h;j++)   {   m_dib.SetPixel(i,j,RGB(255,255,255));   if(i==10)  i=w-10;   if(j==10)  j=h-10;   }  for(i=0;i<w;i++)   for(int j=0;j<h;j++)   {   DWORD rgb=GetPixel(i,j);   int Y=m_dib.FindR(rgb)-m_dib.FindB(rgb);   int y=m_dib.FindR(rgb)-m_dib.FindG(rgb);   if(Y>255)Y=255;   if(Y<0)Y=0;   if(y>255)y=255;   if(y<0)y=0;   Y=Y<y?Yy;   SetPixel(i,j,RGB(Y,Y,Y));   }  int yuZhi=FindAllYu();  for(i=0;i<w;i++)   for(int j=0;j<h;j++)   {<!-- SIPO <DP n="10"> --><dp n="d10"/>   if(m_dib.FindR(GetPixel(i,j))<=yuZhi)   {   ∥ 背景色   SetPixel(i,j,RGB(255,255,255));   }   }   for(i=0;i<w;i++)   for(int j=0;j<h;j++)   {   if(GetPixel(i,j)==RGB(255,255,255))   m_dib.SetPixel(i,j,RGB(255,255,255));   }  if(m_pDIBData!=NULL)   delete m_pDIBData;  m_pDIBData=(BYTE*)new char[m_dib.GetSize()];  memcpy(m_pDIBData,m_dib.m_pDIBData,m_dib.GetSize());  for(i=0;i<w;i++)   for(int j=0;j<h;j++)   {   DWORD rgb=GetPixel(i,j);   int Y=int(-1.368612+0.441683*m_dib.FindR(rgb)+0.390386*m_dib.FindG(rgb)   +0.211932*m_dib.FindB(rgb));   if(Y>255)Y=255;   if(Y<0)Y=0;   SetPixel(i,j,RGB(Y,Y,Y));   }  return true;} 三、图像颜色特征参数提取模块(下面是处理阈值计算的) #ifndef_CThreshold_H_#define_CThreshold_H_∥计算最佳阈值class CThreshold{<!-- SIPO <DP n="11"> --><dp n="d11"/>  enum{N=256};public  CThreshold(){}  ~CThreshold(){}  void set(int g[],int a[],int total=N);  double GetThreshold();protected  double GetOneThreshold(intt);∥计算一个阈值  voidGetUT(); ∥计算图象灰度平均值private  int gray[N],n[N],m_total,m_ntotal;  double m_ut,m_threshold;∥图象灰度平均值};#endif∥_CThreshold_H_#include″stdafx.h″#include″Threshold.h″#define SQR(x)(x)*(x)void CThreshold∷set(int g[],iht a[],int total){  m_total=total;  for(int i=0;i<m_total;i++){  n[i]=a[i];  gray[i]=g[i];  }  GetUT();}void CThreshold∷GetUT(){  int nTotal=0;  m_ut=0.0;m_ntotal=0;  for(int i=0;i<m_total;i++)   nTotal+=n[i];  for(i=0;i<m_total;i++){   m_ut+=1.0*gray[i]*n[i]/nTotal;   m_ntotal+=n[i];  }}double CThreshold∷GetOneThreshold(int t)<!-- SIPO <DP n="12"> --><dp n="d12"/>{  ∥计算类C1的像素灰度平均值和方差,发生概率  double u1=0.0,s1=0.0,w1=0.0;  int total=0;  for(int i=0;i<t;i++)total+=n[i];  for(i=0;i<t;i++){   u1+=1.0*gray[i]*n[i]/total;   w1+=1.0*n[i]/m_ntotal;  }  for(i=0;i<t;i++)s1+=1.0*SQR(gray[i]-u1)*n[i]/total;  ∥计算类C2的像素灰度平均值和方差  double u2=0.0,s2=0.0,w2=0.0;  total=0;  for(i=t;i<m_total;i++)total+=n[i];  for(i=t;i<m_total;i++){   u2+=1.0*gray[i]*n[i]/total;   w2+=1.0*n[i]/m_ntotal;  }  for(i=t;i<m_total;i++)s2+=1.0*SQR(gray[i]-u2)*n[i]/total;  double sw2=w1*s1+w2*s2;  double sb2=w1*SQR(u1-m_ut)+w2*SQR(u2-m_ut);  return sb2/sw2;}double CThreshold∷GetThreshold(){  m_threshold=0;  double nSepMax=0.0;∥求分离度最大的值  for(int t=0;t<m_total;t++){   double temp=GetOneThreshold(gray[t]);   if(temp>nSepMax){   nSepMax=temp;   m_threshold=gray[t];   }  }  return m_threshold;}用递归方法去除颜色值void CJiSuan∷FillGreenColor(int x,int y){<!-- SIPO <DP n="13"> --><dp n="d13"/>  if(x<0‖x>m_dib.GetDIBWidth()‖y<0‖y>m_dib.GetDIBHeight())   return;  if(GetPixel(x,y)==RGB(255,0,255))   SetPixel(x,y,RGB(255,255,255));  else   return;  FillGreenColor(x+1,y);  FillGreenColor(x-1,y);  FillGreenColor(x,y-1);  FillGreenColor(x,y+1);}图像位图像素操作类∥DIB.cppimplementation file∥#include″stdafx.h″#include″DIB.h″#ifdef_DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE[]=_FILE_;#endif///////////////////////////////////////////////////////////////////////////////////∥CDIBCDIB∷CDIB(){  m_pBMI=NULL;  m_pDIBData=NULL;  m_pDIBData2=NULL;}CDIB∷~CDIB(){  if(m_pBMI!=NULL)   delete m_pBMI;  if(m_pDIBData!=NULL)   delete m_pDIBData;  if(m_pDIBData2!=NULL)   delete m_pDIBData2;}<!-- SIPO <DP n="14"> --><dp n="d14"/>BOOL CDIB∷LoadFromFile(LPCTSTR lpszFileName){  CFile file;  BITMAPINFO*pBMI=NULL;  BYTE*pDIBData=NULL;  if(!file.Open(lpszFileName,CFile∷modeRead|CFile∷typeBinary))  {  AfxMessageBox(″打不开文件″);  return false;  }  BITMAPFILEHEADER bfh;  if(file.Read(&amp;bfh,sizeof(bfh))!=sizeof(bfh))  {  AfxMessageBox(″读文件出错″);  return false;  }  if(bfh.bfType!=0x4d42)  {  AfxMessageBox(″不是bmp文件″);  return false;  }  BITMAPINFOHEADER bih;  if(file.Read(&amp;bih,sizeof(bih))!=sizeof(bih))  {  AfxMessageBox(″读文件出错″);  return false;  }  if(bih.biBitCount!=24)  {  AfxMessageBox(″不是24位图片″);  return false;  }  pBMI=(BITMAPINFO*)new char[sizeof(BITMAPINFOHEADER)];  if(!pBMI)  {  AfxMessageBox(″分配内存出错″);  return false;  }  memcpy(pBMI,&amp;bih,sizeof(BITMAPINFOHEADER));<!-- SIPO <DP n="15"> --><dp n="d15"/>  DWORD dataBytes=bfh.bfSize-bfh.bfOffBits;  m_size=dataBytes;  pDIBData=(BYTE*)new char[dataBytes];  if(!pDIBData)  {  AfxMessageBox(″分配内存出错″);  delete pBMI;  return false;  }  if(file.ReadHuge(pDIBData,dataBytes)!=dataBytes)  {  AfxMessageBox(″读文件出错″);  delete pBMI;  delete pDIBData;  return false;  }  file.Close();  if(m_pBMI!=NULL)  delete m_pBMI;  m_pBMI=pBMI;  if(m_pDIBData!=NULL)  delete m_pDIBData;  m_pDIBData=pDIBData;  return true;}void CDIB∷ShowDIB(CDC*pDC,int nLeft,int nTop,int nWidth,int nHeight){  pDC->SetStretchBltMode(COLORONCOLOR);  StretchDIBits(pDC->GetSafeHdc(),nLeft,nTop,nWidth,nHeight,  0,0,GetDIBWidth(),GetDIBHeight(),  m_pDIBData,m_pBMI,DIB_RGB_COLORS,SRCCOPY);}////////////////////////////////////////////////////////////////////////////∥CDIB message handlersDWORD CDIB∷GetPixel(int x,int y){<!-- SIPO <DP n="16"> --><dp n="d16"/>  if(m_pDIBData==NULL)  {  AfxMessageBox(″没有加载图像!″);  return-1;  }  ∥一行的字节数。  return dib_GetColor(m_pDIBData+m_nPitch*y+x+x+x);}void CDIB∷SetPixel(int x,int y,DWORD c){∥dib_SetColor((BYTE*)(),c);  ∥一行的字节数。  dib_SetColor((BYTE*)(m_pDIBData+m_nPitch*y+x+x+x),c);}void CDIB∷SaveImage(LPCTSTR lpszName){  BITMAPFILEHEADER bfh;  memset(&amp;bfh,0,sizeof(BITMAPFILEHEADER));  BITMAPINFOHEADER bi;  bi.biSize =sizeof(BITMAPINFOHEADER);  bi.biWidth =GetDIBWidth();  bi.biHeight=GetDIBHeight();  bi.biPlanes =1;  bi.biBitCount =24;∥m_dib.m_nPitch*m_dib.GetDIBHeight();  bi.biCompression =BI_RGB;  bi.biSizeImage =0;  bi.biXPelsPerMeter =0;  bi.biYPelsPerMeter =0;  bi.biClrUsed =0;  bi.biClrImportant =0;  if(bi.biSizeImage==0)  bi.biSizeImage=((((bi.biWidth*bi.biBitCount)+31)&amp;~31)/8)  *bi.biHeight;  bfh.bfType=((WORD)′B′)′M′<<8;  bfh.bfSize=sizeof(BITMAPFILEHEADER)   +sizeof(BITMAPINFOHEADER)   +bi.biSizeImage;  bfh.bfOffBits=sizeof(BITMAPFILEHEADER)   +sizeof(BITMAPINFOHEADER);<!-- SIPO <DP n="17"> --><dp n="d17"/>  HANDLE hFile=CreateFile(lpszName,GENERIC_WRITE,0,0,   CREATE_ALWAYS,0,0);  DWORD dw;  WriteFile(hFile,&amp;bfh,sizeof(BITMAPFILEHEADER),&amp;dw,NULL);  WriteFile(hFile,&amp;bi,sizeof(BITMAPINFOHEADER),&amp;dw,NULL);  WriteFile(hFile,m_pDIBData,bi.biSizeImage,&amp;dw,NULL);  CloseHandle(hFile);}int CDIB∷FindB(DWORD rgb){  DWORD b=rgb &amp; 0x000000ff;return int(b);}int CDIB∷FindR(DWORD rgb){  ∥查找RGB色彩  DWORD r=rgb &amp; 0x00ff0000;  r=r/(16*16*16*16);  return int(r);}int CDIB∷FindG(DWORD rgb){  DWORD g=rgb &amp; 0x0000ff00;  g=g/(16*16);  return int(g);}DWORD CDIB∷GetSize(){  return m_size;} 四、猪肉颜色等级输出模块(图片格式转化操作类) #include″stdafx.h″#include″Picture.h″<!-- SIPO <DP n="18"> --><dp n="d18"/>  #ifdet_DEBUG  #define new DEBUG_NEW  #undef THIS_FILE  static char THIS_FILE[]=_FILE_;  #endif  #define HIMETRIC_INCH 2540  #define ERROR_TITLE″CPicture Error″∥Error Title(Related To This Class)...  ∥-----------------------------------------------------------------------------  ∥DoesConstructor-Create a New CPicture Object To Hold Pictre Data  ∥~~~~  ∥  ∥-----------------------------------------------------------------------------  CPicture∷CPicture()  ∥=============================================================================  {  m_IPicture=NULL;  m_Height=0;  m_Weight=0;  m_Width=0;  }  ∥-----------------------------------------------------------------------------  ∥DoesDestructor-Free Data And Information From The CPicture Object  ∥~~~~  ∥  ∥-----------------------------------------------------------------------------  CPicture∷~CPicture()  ∥=============================================================================  {  if(m_IPicture!=NULL)FreePictureData();∥Important-Avoid Leaks...  }  void CPicture∷FreePictureData()  ∥=============================================================================  {  if(m_IPicture !=NULL)  {  m_IPicture->Release();  m_IPicture=NULL;  m_Height=0;<!-- SIPO <DP n="19"> --><dp n="d19"/>  m_Weight=0;  m_Width=0;  }  }  ∥-----------------------------------------------------------------------------  ∥DoesOpen a Resource And Load It Into IPicture(Interface)  ∥~~~~ (.BMP.DIB.EMF.GIF.ICO.JPG.WMF)  ∥  ∥NoteWhen Adding a Bitmap Resource It Would Automatically Show On″Bitmap″  ∥~~~~ This NOT Good Coz We Need To Load It From a Custom Resource″BMP″  ∥ To Add a Custom RresourceImport Resource->Open As->Custom  ∥ (Both.BMP And.DIB Should Be Found Under″BMP″)  ∥  ∥InPut ResourceName-As a UINT Defined(ExampleIDR_PICTURE_RESOURCE)  ∥~~~~~ ResourceType-Type Name(Example″JPG″)  ∥  ∥OutPutTRUE If Succeeded...  ∥~~~~~~  ∥-----------------------------------------------------------------------------  BOOL CPicture∷Load(UINT ResourceName,LPCSTR ResourceType)  ∥=============================================================================  {  BOOL bResult=FALSE;  HGLOBAL hGlobal=NULL;  HRSRChSource=NULL;  LPVOID lpVoid =NULL;  int nSize =0;  if(m_IPicture!=NULL)FreePictureData();∥Important-Avoid Leaks...  hSource=FindResource(AfxGetResourceHandle(),MAKEINTRESOURCE(ResourceName),ResourceType);  if(hSource==NULL)  {  HWND hWnd=AfxGetApp()->GetMainWnd()->m_hWnd;  MessageBoxEx(hWnd,″FindResource()Failed\t″,ERROR_TTTLE,MB_OK|MB_ICONSTOP,LANG_ENGLISH);  return(FALSE);  }<!-- SIPO <DP n="20"> --><dp n="d20"/>   hGlobal=LoadResource(AfxGetResourceHandle(),hSource);   if(hGlobal==NULL)   {   HWND hWnd=AfxGetApp()->GetMainWnd()->m_hWnd;   MessageBoxEx(hWnd,″LoadResource()Failed\t″,ERROR_TITLE,MB_OKMB_ICONSTOP,LANG_ENGLISH);   return(FALSE);   }   lpVoid=LockResource(hGlobal);   if(lpVoid==NULL)   {   HWND hWnd=AfxGetApp()->GetMainWnd()->m_hWnd;   MessageBoxEx(hWnd,″LockResource()Failed\t″,ERROR_TITLE,MB_OKMB_ICONSTOP,LANG_ENGLISH);   return(FALSE);   }   nSize=(UINT)SizeofResource(AfxGetResourceHandle(),hSource);   if(LoadPictureData((BYTE*)hGlobal,nSize))bResult=TRUE;   UnlockResource(hGlobal);∥16Bit Windows Needs This   FreeResource(hGlobal);∥16Bit Windows Needs This(32Bit-Automatic Release)   m_Weight=nSize;∥Update Picture Size Info...   if(m_IPicture!=NULL)∥Do Not Try To Read From Memory That Is Not Exist...   {   m_IPicture->get_Height(&amp;m_Height);   m_IPicture->get_Width(&amp;m_Width);   ∥Calculate Its Size On a″Standard″(96 DPI)Device Context   m_Height=MulDiv(m_Height,96,HIMETRIC_INCH);   m_Width=MulDiv(m_Width,96,HIMETRIC_INCH);   }   else∥Picture Data Is Not a Known Picture Type   {   m_Height=0;   m_Width=0;   bResult=FALSE;   }   return(bResult);   }<!-- SIPO <DP n="21"> --><dp n="d21"/>  ∥-----------------------------------------------------------------------------  ∥DoesOpen a File And Load It Into IPicture(Intefface)  ∥~~~~ (.BMP.DIB.EMF.GIF.ICO.JPG.WMF)  ∥  ∥InPut sFilePathName-Path And FileName Target To Save  ∥~~~~~  ∥  ∥OutPutTRUE If Succeeded...  ∥~~~~~~  ∥-----------------------------------------------------------------------------  BOOL CPicture∷Load(CString sFilePathName)  ∥============================================================================  {  BOOL bResult=FALSE;  CFile PictureFile;  CFileException e;  int nSize=0;  if(m_IPicture!=NULL)FreePictureData();∥Important-Avoid Leaks...  if(PictureFile.Open(sFilePathName,CFile∷modeRead|CFile∷typeBinary,&amp;e))   {   nSize=PictureFile.GetLength();   BYTE*pBuffer=new BYTE[nSize];   if(PictureFile.Read(pBufier,nSize)>0)  {  if(LoadPictureData(pBufier,nSize))bResult=TRUE;  }   PictureFile.Close();   delete[]pBuffer;   }  else∥Open Failed...  {  TCHAR szCause[255];  e.GetErrorMessage(szCause,255,NULL);  CString str=szCause;  if(str.Find(″sharing″)<0)  {  HWND hWnd=AfxGetApp()->GetMainWnd()->m_hWnd;  MessageBoxEx(hWnd,szCause,ERROR_TITLE,MB_OK|MB_ICONSTOP,LANG_ENGLISH);<!-- SIPO <DP n="22"> --><dp n="d22"/>  }  bResult=FALSE;  } m_Weight=nSize;∥Update Picture Size Info...if(m_IPicture!=NULL)∥Do Not Try To Read From Memory That Is Not Exist...{m_IPicture->get_Height(&amp;m_Height);m_IPicture->get_Width(&amp;m_Width);∥Calculate Its Size On a″Standard″(96 DPI)Device Contextm_Height=MulDiv(m_Height,96,HIMETRIC_INCH);m_Width=MulDiv(m_Width,96,HIMETRIC_INCH);}else∥Picture Data Is Not a Known Picture Type{m_Height=0;m_Width=0;bResult=FALSE;}return(bResult);}BOOL CPicture∷LoadPictureData(BYTE*pBuffer,int nSize)∥============================================================================={BOOL bResult=FALSE;HGLOBAL hGlobal=GlobalAlloc(GMEM_MOVEABLE,nSize);if(hGlobal==NULL){HWND hWnd=AfxGetApp()->GetMainWnd()->m_hWnd;MessageBoxEx(hWnd,″Can not allocate enough memory\t″,ERROR_TITLE,MB_OK |MB_ICONSTOP,LANG_ENGLISH);return(FALSE);}void*pData=GlobalLock(hGlobal);memcpy(pData,pBuffer,nSize);GlobalUnlock(hGlobal);IStream*pStream=NULL;<!-- SIPO <DP n="23"> --><dp n="d23"/>  if(CreateStreamOnHGlobal(hGlobal,TRUE,&amp;pStream)==S_OK)  {  HRESULT hr;  if((hr=OleLoadPicture(pStream,nSize,FALSE,IID_IPicture,(LPVOID*)&amp;m_IPicture))==E_NOINTERFACE)  {  HWND hWnd=AfxGetApp()->GetMainWnd()->m_hWnd;  MessageBoxEx(hWnd,″IPicture interface is not supported\t″,ERROR_TITLE,MB_OK|MB_ICONSTOP,LANG_ENGLISH);  return(FALSE);  }  else∥S_OK  {  pStream->Release();  pStream=NULL;  bResult=TRUE;  }  }  FreeResource(hGlobal);∥16Bit Windows Needs This(32Bit-Automatic Release)  return(bResult);  }  BOOL CPicture∷Show(CDC*pDC,CRect DrawRect)  ∥=============================================================================  {  if(pDC==NULL‖m_IPicture==NULL)return FALSE;  long Width=0;  long Height=0;  m_IPicture->get_Width(&amp;Width);  m_IPicture->get_Height(&amp;Height);  HRESULT hrP=NULL;  hrP=m_IPicture->Render(pDC->m_hDC,   DrawRect.left,∥Left   DrawRect.top, ∥Top   DrawRect.right-DrawRect.left,∥Right   DrawRect.bottom-DrawRect.top,∥Bottom<!-- SIPO <DP n="24"> --><dp n="d24"/>   0,   Height,   Width,   -Height,   &amp;DrawRect);  if(SUCCEEDED(hrP))return(TRUE);  HWND hWnd=AfxGetApp()->GetMainWnd()->m_hWnd;  MessageBoxEx(hWnd,″Can not allocate enough memory\t″,ERROR_TITLE,MB_OK|MB_ICONSTOP,LANG_ENGLISH);  return(FALSE);  }  ∥-----------------------------------------------------------------------------  ∥DoesDraw The Loaded Picture Direct To The Client DC  ∥~~~~  ∥  ∥NoteBigger OR Smaller Dimentions Than The Original Picture Size  ∥~~~~ Will Draw The Picture Streached To Its New Given Dimentions...  ∥  ∥InPut pDC-Given DC To Draw On  ∥~~~~~ LeftTop-Opening Point To Start Drawing(Left,Top)  ∥ WidthHeight-Dimentions Of The Picture To Draw(Width,Height)  ∥ MagnifyX-Magnify Pixel Width,0=Default(No Magnify)  ∥ MagnifyY-Magnify Pixel Height,0=Default(No Magnify)  ∥  ∥OutPutTRUE If Succeeded...  ∥~~~~~~  ∥-----------------------------------------------------------------------------  BOOL CPicture∷Show(CDC*pDC,CPoint LeftTop,CPoint WidthHeight,int MagnifyX,intMagnifyY)  ∥=============================================================================  {  if(pDC==NULL‖m_IPicture==NULL)return FALSE;  long Width=0;  long Height=0;  m_IPicture->get_Width(&amp;Width);  m_IPicture->get_Height(&amp;Height);  if(MagnifyX==NULL)MagnifyX=0;  if(MagnifyY==NULL)MagnifyY=0;  MagnifyX=int(MulDiv(Width,pDC->GetDeviceCaps(LOGPIXELSX),HIMETRIC_INCH)*<!-- SIPO <DP n="25"> --><dp n="d25"/>MagnifyX);  MagnifyY=int(MulDiv(Height,pDC->GetDeviceCaps(LOGPIXELSY),HIMETRIC_INCH)*Magnifyy);  CRect DrawRect(LeftTop.x,LeftTop.y,MagnifyX,Magnifyy);  HRESULT hrP=NULL;    hrp=m_IPicture->Render(pDC->m_hDC,   LeftTop.x, ∥Left   LeftTop.y, ∥Top   WidthHeight.x+MagnifyX,∥Width   WidthHeight.y+MagnifyY,∥Height   0,   Height,   Width,   -Height,   &amp;DrawRect);  if(SUCCEEDED(hrP))return(TRUE);  HWND hWnd=AfxGetApp()->GetMainWnd()->m_hWnd;  MessageBoxEx(hWnd,″Can not allocate enough memory\t″,ERROR_TITLE,MB_OK|MB_ICONSTOP,LANG_ENGLISH);  return(FALSE);  }  ∥-----------------------------------------------------------------------------  ∥DoesSaves The Picture That Is Stored In The IPicture Object As a Bitmap  ∥~~~~ (Converts From Any Known Picture Type To a Bitmap/Icon File)  ∥  ∥InPut sFilePathName-Path And FileName Target To Save  ∥~~~~~  ∥  ∥OutPutTRUE If Succeeded...  ∥~~~~~~  ∥-----------------------------------------------------------------------------  BOOL CPicture∷SaveAsBitmap(CString sFilePathName)  ∥=============================================================================  {  BOOL bResult=FALSE;  ILockBytes*Buffer=0;  IStorage *pStorage=0;<!-- SIPO <DP n="26"> --><dp n="d26"/>  IStream *FileStream=0;  BYTE *BufferBytes;  STATSTG BytesStatistics;  DWORD OutData;  longOutStream;  CFile BitmapFile;CFileException e;  double SkipFloat=0;  DWORD ByteSkip=0;  _ULARGE_INTEGER RealData;  CreateILockBytesOnHGlobal(NULL,TRUE,&amp;Buffer);∥Create ILockBytes Buffer  HRESULT hr=∷StgCreateDocfileOnILockBytes(Buffer,   STGM_SHARE_EXCLUSIVE|STGM_CREATE|STGM_READWRITE,0,&amp;pStorage);  hr=pStorage->CreateStream(L″PICTURE″,   STGM_SHARE_EXCLUSIVE|STGM_CREATE|STGM_READWRITE,0,0,&amp;FileStream);  m_IPicture->SaveAsFile(FileStream,TRUE,&amp;OutStream);∥Copy Data Stream  FileStream->Release();  pStorage->Release();  Buffer->Flush();  ∥m_IPicture->SaveAsFile(  ∥Get Statistics For Final Size Of Byte Array  Buffer->Stat(&amp;BytesStatistics,STATFLAG_NONAME);  ∥Cut UnNeeded Data Coming From SaveAsFile()(Leave Only″Pure″Picture Data)  SkipFloat=(double(OutStream)/512);∥Must Be In a 512 Blocks...  if(SkipFloat>DWORD(SkipFloat))ByteSkip=(DWORD)SkipFloat+1;  else ByteSkip=(DWORD)SkipFloat;  ByteSkip=ByteSkip*512;∥Must Be In a 512 Blocks...  ∥Find Difference Between The Two Values  ByteSkip=(DWORD)(BytesStatistics.cbSize.QuadPart-ByteSkip);  ∥Allocate Only The″Pure″Picture Data  RealData.LowPart=0;  RealData.HighPart=0;  RealData.QuadPart=ByteSkip;  BufferBytes=(BYTE*)malloc(OutStream);  if(BufferBytes==NULL)  {  Buffer->Release();<!-- SIPO <DP n="27"> --><dp n="d27"/>  HWND hWnd=AfxGetApp()->GetMainWnd()->m_hWnd;  MessageBoxEx(hWnd,″Can not allocate enough memory\t″,ERROR_TITLE,MB_OK|MB_ICONSTOP,LANG_ENGLISH);  }   Buffer->ReadAt(RealData,BufferBytes,OutStream,&amp;OutData);   if(BitmapFile.Open(sFilePathName,CFile∷typeBinary|CFile∷modeCreate|CFile∷modeWrite,&amp;e))  {  BitmapFile.Write(BufferBytes,OutData);  BitmapFile.Close();  bResult=TRUE;  }  else∥Write File Failed...  {  TCHAR szCause[255];  e.GetErrorMessage(szCause,255,NULL);  HWND hWnd=AfxGetApp()->GetMainWnd()->m_hWnd;   MessageBoxEx(hWnd,szCause,ERROR_TITLE,MB_OK|MB_ICONSTOP,LANG_ENGLISH);  bResult=FALSE;  }  Buffer->Release();  free(BufferBytes);  return(bResult);  }  BOOL CPicture∷ShowBitmapResource(CDC*pDC,const int BMPResource,CPoint LeftTop)  ∥=============================================================================  {  if(pDC==NULL)return(FALSE);  CBitmap BMP;  if(BMP.LoadBitmap(BMPResource))  {  ∥Get Bitmap Details  BITMAP BMPInfo;  BMP.GetBitmap(&amp;BMPInfo);  ∥Create An In-Memory DC Compatible With The Display DC We R Gonna Paint On  CDC DCMemory;  DCMemory.CreateCompatibleDC(pDC);  ∥Select The Bitmap Into The In-Memory DC  CBitmap*pOldBitmap=DCMemory.SelectObject(&amp;BMP);  ∥Copy Bits From The In-Memory DC Into The On-Screen DC  pDC->BitBlt(LeftTop.x,LeftTop.y,BMPInfo.bmWidth,BMPInfo.bmHeight,&amp;DCMemory,0,0,SRCCOPY);<!-- SIPO <DP n="28"> --><dp n="d28"/>  DCMemory.SelectObject(pOldBitmap);∥(As Shown In MSDN Example...)  }  else  {  TRACE0(″ERRORCan Not Find The Bitmap Resource\n″);  return(FALSE);  }  return(TRUE);  }  ∥-----------------------------------------------------------------------------  ∥DoesGet The Original Picture Pixel Size(Ignor What Current DC Is Using)  ∥~~~~ Pointer To a Device Context Is Needed For Pixel Calculation,  ∥  ∥ Also Updates The Class′s Height And Width Properties,  ∥ (Coz Till Now We Had No Device Context To Work With...96 DPI Assumed)  ∥  ∥InPut The Client DC(Needed To Check The Size Of The Pixels)  ∥~~~~~  ∥  ∥OutPutTRUE If Succeeded...  ∥~~~~~~  ∥-----------------------------------------------------------------------------  BOOL CPicture∷UpdateSizeOnDC(CDC*pDC)  ∥======================================================================  {  if(pDC==NULL‖m_IPicture==NULL){m_Height=0;m_Width=0;return(FALSE);};  m_IPicture->get_Height(&amp;m_Height);  m_IPicture->get_Width(&amp;m_Width);   ∥Get Current DPI-Dot Per Inch  int CurrentDPI_X=pDC->GetDeviceCaps(LOGPIXELSX);  int CurrentDPI_Y=pDC->GetDeviceCaps(LOGPIXELSY);   ∥Use a″Standard″Print(When Printing)  if(pDC->IsPrinting())  {  CurrentDPI_X=96;  CurrentDPI_Y=96;  }  m_Height=MulDiv(m_Height,CurrentDPI_Y,HIMETRIC_INCH);  m_Width =MulDiv(m_Width,CurrentDPI_X,HIMETRIC_INCH);  return(TRUE);  }
权利要求
1、一种猪肉颜色分级仪器,包括图像采集设备和猪肉颜色分级软件,其特征在于
(1)图像获取设备包括图像采集室4、数码相机5
图像采集室4为直径为600mm的半球形耐高温材料制成,内壁涂成白色,4个50W卤素灯1等间距安装于图像采集室4的底部,图像采集室4内的载样台2面为用细砂布打磨过的黑色橡胶板,样品3置于橡胶板上,图像采集室4顶端开一直径为45mm圆孔;
选用CANON-PowerShotA70数码相机5,镜头穿过于图像采集室4顶圆孔;
(2)猪肉颜色分级软件
猪肉颜色计算机分级软件由图像输入控制模块、图像分割与识别模块、图像颜色特征参数提取模块、猪肉颜色等级输出模块组成
a、图像输入控制模块可以自动打开数码相机5镜头、自动拍摄样品3的彩色图像;
b、图像分割与识别模块用于对输入的彩色图像进行去噪、去背景、边缘提取,最终获取猪肉图像的有效特征颜色提取区域;
c、图像颜色特征参数提取模块用于对图像分割与识别模块获取的有效颜色提取区域提取图像的颜色特征参数,包括红色R、绿色G、蓝色B、色彩H、饱和度S、亮度V;
d、猪肉颜色等级输出模块用于调用猪肉颜色等级模型猪肉颜色等级G=4.62+6.63*S-10.20*V,输出猪肉颜色级别。
全文摘要
本项发明“猪肉颜色分级仪”属于农产品质量自动分级领域,包括图像采集设备和猪肉颜色分级软件。图像采集室4为直径为600mm的半球形耐高温材料制成,内壁涂成白色,4个50W卤素灯1等间距安装于图像采集室4的底部,样品3置于图像采集室4内的载样台2上,选用CANON-Power Shot A70数码相机5,镜头穿过于图像采集室4顶圆孔;分级软件由图像输入控制模块、图像分割与识别模块、图像颜色特征参数提取模块、猪肉颜色等级输出模块组成,猪肉颜色等级G=4.62+6.63*S-10.20*V。本发明可以将猪肉按照猪肉颜色分级标准进行计算机在线分级,指导猪肉“按级论价”,适用于超市零售。
文档编号G01N21/84GK1619295SQ20041009890
公开日2005年5月25日 申请日期2004年12月10日 优先权日2004年12月10日
发明者徐幸莲, 彭增起, 江龙建 申请人:南京农业大学

  • 专利名称:皮带轮耐久试验系统的制作方法技术领域:本实用新型涉及皮带轮的耐久测试,具体地指一种能够通过模拟实际工况测试皮带轮寿命的皮带轮耐久试验系统。背景技术:近几年随着经济的发展汽车行业也得到高速发展,带动了国内皮带轮生产行业的快速发展,国
  • 专利名称:一种用于测试斗齿触土性能的实验装置的制作方法技术领域:本实用新型涉及ー种测试实验装置,尤其是涉及ー种用于测试斗齿触土性能的实验装置。 背景技术:目前,针对斗齿的性能实验通常专注于斗齿的强度、刚度、疲劳强度和摩擦学性能等,很少对的斗
  • 专利名称:一种新型的故障采集终端的制作方法技术领域:本实用新型涉及一种新型的故障采集终端,尤其涉及一种从线路电流互感器CT 获取电源的故障采集终端。背景技术:随着国民经济飞速发展,用户对电网稳定性与可靠性要求越来越高,因此当供电系统出现故障
  • 专利名称:诊断甲状腺疾病的手段和方法诊断甲状腺疾病的手段和方法本发明涉及用于诊断甲状腺疾病的方法。其还涉及测定化合物是否能在受试者中诱发甲状腺疾病的方法,以及涉及鉴定用于治疗甲状腺疾病的药物的方法。此外,本发明涉及用于诊断甲状腺疾病的装置和
  • 专利名称:车用传感器的传感头的制作方法技术领域:车用传感器的传感头技术领域:本实用新型涉及一种传感器,具体涉及一种车用传感器的传感头。背景技术:车用传感器包括ABS防抱死系统传感器、曲轴位置传感器、凸轮轴位置传感器等,它对汽车的安全驾驶及自
  • 专利名称:粉尘含量在线监测装置的制作方法技术领域:本实用新型属于一种测量仪器,尤其是一种粉尘含量在线监测装置。广泛应用于冶金、发电、石油、化工、医药、建材加工、采煤、采矿、水泥和包装等行业气固两相流的含尘量在线监测。典型应用炼铁高炉煤气总管
山东科威数控机床有限公司
全国服务热线:13062023238
电话:13062023238
地址:滕州市龙泉工业园68号
关键词:铣床数控铣床龙门铣床
公司二维码
Copyright 2010-2024 http://www.ruyicnc.com 版权所有 All rights reserved 鲁ICP备19044495号-12