連通ドメイン抽出


ゾーン成長に基づく方法
単一スキャンのアルゴリズムには、領域成長に基づく連通領域マーキングアルゴリズムがあり、アルゴリズムの流れは以下の通りである.
  • タグ対象画像bitmapを入力し、入力画像と同じサイズのタグマトリクスlabelmap、キューqueue、タグカウントlabelIndexを初期化する.
  • 左から右、上から下の順にbitmapをスキャンし、マークされていない前景画素pをスキャンすると、labelIndexに1を加え、labelmapにp(対応する点の値はlabelIndexに与えられる)をマークするとともに、pの8隣接点をスキャンし、マークされていない前景画素が存在する場合、labelmapにマークを行い、queueに入れ、領域成長の種子とする.
  • queueが空でない場合、queueから成長シード点p 1を取り出し、p 1の8隣接点を走査し、マークされていない前景画素が存在する場合、labelmapにマークし、queueに入れる.
  • queueが空になるまで3を繰り返し、1つの連通領域フラグが完了する.
  • は、画像全体がスキャンされるまで2に進み、タグマトリクスlabelmapと連通領域の個数labelIndexが得られる.

  • 以上は領域成長に基づいて連通領域抽出を行うステップであり,実際の動作ではその中のqueueを修正し,2つのポインタ(1つのポインタヘッド,1つのポインタテール)を用いて動作した.
    <pre name="code" class="cpp">typedef struct _IVT_QUEUE
    {
    	IVT_POINT	       point;
    	int			nIndex;
    }IVT_QUEUE,*pIVT_QUEUE;
    typedef struct _IVT_BLOB_
    {
    	IVT_RECT             BlobRect;
    	int			nArea;
    }IVT_BLOB;
    int*       m_pLabelmap = NULL;
    m_pLabelmap = new int[m_nMulti];
     
      
    <pre name="code" class="cpp">int ConnectedComponentROI(unsigned char* pImgData,  IVT_BLOB* pBlob)
    {
    	IVT_QUEUE       *pHead,*pEnd;
    	int		labelIndex=0,nIndex,i,cx,cy;
    	int		nCreateBlobNum=0;		
    
    	memset(m_pLabelmap, 0, m_nMulti * sizeof(int));
    
    	for (cy=1; cy<m_nHeight-1; cy++)
    	{
              for(cx=1;cx<m_nWidth-1;cx++)
    	  {
    		nIndex = cy*m_nWidth+cx;
    		if (pImgData[nIndex]&(!m_pLabelmap[nIndex]))
    		{
    			pEnd = pHead = m_pQueue;
    
    			m_pNewBlob->nTop = cy;
    			m_pNewBlob->nLeft = cx;
    			m_pNewBlob->nRight = cx;
    			m_pNewBlob->nBottom = cy;
    			pHead->nIndex = nIndex;
    			pHead->point.x = pInder->nWidth;
    			pHead->point.y = pInder->nHeight;
    			labelIndex++;
    			SearchNeighbor(pImgData,pHead,labelIndex, nIndex, m_pLabelmap, pEnd);
    
    			while(pHead!=pEnd)
    			{
    				SearchNeighbor(pImgData, pHead,labelIndex, m_pLabelmap, pEnd);
    				pHead++;;
    			}
    
    			if (nCreateBlobNum>999)
    			{
    				printf("BlobNum too many!\r
    "); return -1; } pBlob[nCreateBlobNum].BlobRect = m_pNewBlob; nCreateBlobNum++; } } nCreateBlobNum = CombineBlob(nCreateBlobNum,pBlob); nCreateBlobNum = DeleteSmallBlob(nCreateBlobNum,pBlob); return nCreateBlobNum; }
    
    
     
      
    void SearchNeighbor(unsigned char* pImgData,IVT_QUEUE *pQueue, int labelIndex,int* &pLabelmap,IVT_QUEUE* &pEnd)
    {
    	int		        searchIndex,i; 
    	int				nCx,nCy;
    	pLabelmap[pQueue->nIndex] = labelIndex;
    	nCx = pQueue->point.x;
    	nCy = pQueue->point.y;
    
    	//  {0,1}
    	searchIndex = pQueue->nIndex + 1;
    	if ( (searchIndex>=0) && (nCx+1 <m_nWidth) && (255 == pImgData[searchIndex]) &&(!pLabelmap[searchIndex]))
    	{
    		pLabelmap[searchIndex] = labelIndex;
    		m_pNewBlob->nRight = m_pNewBlob->nRight>nCx+1?m_pNewBlob->nRight:nCx+1;
    		pEnd->nIndex = searchIndex;
    		pEnd->point.x = nCx+1;
    		pEnd->point.y = nCy;
    		pEnd++;
    	}
    
    	//  {1,1}
    	searchIndex = pQueue->nIndex + m_nWidth + 1;
    	if ((searchIndex>=0) && (nCx+1<m_nWidth) && (nCy+1<m_nHeight) && (255 == pImgData[searchIndex]) && (!pLabelmap[searchIndex]))
    	{
    		pLabelmap[searchIndex] = labelIndex;
    		m_pNewBlob->nRight = m_pNewBlob->nRight>nCx+1?m_pNewBlob->nRight:nCx+1;
    		m_pNewBlob->nBottom = m_pNewBlob->nBottom>nCy+1?m_pNewBlob->nBottom:nCy+1;
    		pEnd->nIndex = searchIndex;
    		pEnd->point.x = nCx+1;
    		pEnd->point.y = nCy+1;
    		pEnd++;
    	}
    
    	//  {1,0}
    	searchIndex = pQueue->nIndex + m_nWidth;
    	if ((searchIndex>=0) && (nCy+1<m_nHeight) && (255 == pImgData[searchIndex]) &&(!pLabelmap[searchIndex]))
    	{
    		pLabelmap[searchIndex] = labelIndex;
    		m_pNewBlob->nBottom = m_pNewBlob->nBottom>nCy+1?m_pNewBlob->nBottom:nCy+1;
    		pEnd->nIndex = searchIndex;
    		pEnd->point.x = nCx;
    		pEnd->point.y = nCy+1;
    		pEnd++;
    	}
    
    	//  {1,-1}
    	searchIndex = pQueue->nIndex + m_nWidth - 1;
    	if ((searchIndex>=0) && (nCx-1>=0) && (nCy+1<m_nHeight) && (255 == pImgData[searchIndex]) &&(!pLabelmap[searchIndex]))
    	{
    		pLabelmap[searchIndex] = labelIndex;
    		m_pNewBlob->nLeft = m_pNewBlob->nLeft<nCx-1?m_pNewBlob->nLeft:nCx-1;
    		m_pNewBlob->nBottom = m_pNewBlob->nBottom>nCy+1?m_pNewBlob->nBottom:nCy+1;
    		pEnd->nIndex = searchIndex;
    		pEnd->point.x = nCx-1;
    		pEnd->point.y = nCy+1;
    		pEnd++;
    	}
    
    	//  {0,-1}
    	searchIndex = pQueue->nIndex - 1;
    	if ((searchIndex>=0) && (nCx-1>=0) && (255 == pImgData[searchIndex]) &&(!pLabelmap[searchIndex]))
    	{
    		pLabelmap[searchIndex] = labelIndex;
    		m_pNewBlob->nLeft = m_pNewBlob->nLeft<nCx-1?m_pNewBlob->nLeft:nCx-1;
    		pEnd->nIndex = searchIndex;
    		pEnd->point.x = nCx-1;
    		pEnd->point.y = nCy;
    		pEnd++;
    	}
    	
    	//  {-1,-1}
    	searchIndex = pQueue->nIndex - m_nWidth - 1;
    	if ((searchIndex>=0) && (nCx-1>=0) && (nCy-1>=0) && (255 == pImgData[searchIndex]) &&(!pLabelmap[searchIndex]))
    	{
    		pLabelmap[searchIndex] = labelIndex;
    		m_pNewBlob->nLeft = m_pNewBlob->nLeft<nCx-1?m_pNewBlob->nLeft:nCx-1;
    		m_pNewBlob->nTop = m_pNewBlob->nTop<nCy-1?m_pNewBlob->nTop:nCy-1;
    		pEnd->nIndex = searchIndex;
    		pEnd->point.x = nCx-1;
    		pEnd->point.y = nCy-1;
    		pEnd++;
    	}
    
    	//  {-1,0}
    	searchIndex = pQueue->nIndex - m_nWidth;
    	if ((searchIndex>=0) && (nCy-1>=0) && (255 == pImgData[searchIndex]) && (!pLabelmap[searchIndex]))
    	{
    		pLabelmap[searchIndex] = labelIndex;
    		m_pNewBlob->nTop = m_pNewBlob->nTop<nCy-1?m_pNewBlob->nTop:nCy-1;
    		pEnd->nIndex = searchIndex;
    		pEnd->point.x = nCx;
    		pEnd->point.y = nCy-1;
    		pEnd++;
    	}
    
    	//  {-1,1}
    	searchIndex = pQueue->nIndex - m_nWidth + 1;
    	if ((searchIndex>=0) && (nCx+1<m_nWidth) && (nCy-1>=0) && (255 == pImgData[searchIndex]) &(!pLabelmap[searchIndex]))
    	{
    		pLabelmap[searchIndex] = labelIndex;
    		m_pNewBlob->nRight = m_pNewBlob->nRight>nCx+1?m_pNewBlob->nRight:nCx+1;
    		m_pNewBlob->nTop = m_pNewBlob->nTop<nCy-1?m_pNewBlob->nTop:nCy-1;
    		pEnd->nIndex = searchIndex;
    		pEnd->point.x = nCx+1;
    		pEnd->point.y = nCy-1;
    		pEnd++;
    	}
    
    	//  {-2,-2}
    	searchIndex = pQueue->nIndex - 2 * m_nWidth - 2;
    	if ( (searchIndex>=0) && (nCx-2>=0) && (nCy-2>=0) && (255 == pImgData[searchIndex]) &&(!pLabelmap[searchIndex]))
    	{
    		pLabelmap[searchIndex] = labelIndex;
    		m_pNewBlob->nLeft = m_pNewBlob->nLeft<nCx-2?m_pNewBlob->nLeft:nCx-2;
    		m_pNewBlob->nTop = m_pNewBlob->nTop<nCy-2?m_pNewBlob->nTop:nCy-2;
    		pEnd->nIndex = searchIndex;
    		pEnd->point.x = nCx-2;
    		pEnd->point.y = nCy-2;
    		pEnd++;
    	}
    
    	//  {-2,-1}
    	searchIndex = pQueue->nIndex - 2 * m_nWidth - 1;
    	if ( (searchIndex>=0) && (nCx-1>=0) && (nCy-2>=0) && (255 == pImgData[searchIndex]) &&(!pLabelmap[searchIndex]))
    	{
    		pLabelmap[searchIndex] = labelIndex;
    		m_pNewBlob->nLeft = m_pNewBlob->nLeft<nCx-1?m_pNewBlob->nLeft:nCx-1;
    		m_pNewBlob->nTop = m_pNewBlob->nTop<nCy-2?m_pNewBlob->nTop:nCy-2;
    		pEnd->nIndex = searchIndex;
    		pEnd->point.x = nCx-1;
    		pEnd->point.y = nCy-2;
    		pEnd++;
    	}
    
    	//  {-2,0}
    	searchIndex = pQueue->nIndex - 2 * m_nWidth;
    	if ( (searchIndex>=0) && (nCy-2>=0) && (255 == pImgData[searchIndex]) &&(!pLabelmap[searchIndex]))
    	{
    		pLabelmap[searchIndex] = labelIndex;
    		m_pNewBlob->nTop = m_pNewBlob->nTop<nCy-2?m_pNewBlob->nTop:nCy-2;
    		pEnd->nIndex = searchIndex;
    		pEnd->point.x = nCx;
    		pEnd->point.y = nCy-2;
    		pEnd++;
    	}
    
    	//  {-2,1}
    	searchIndex = pQueue->nIndex - 2 * m_nWidth + 1;
    	if ( (searchIndex>=0) && (nCx+1<m_nWidth) && (nCy-2>=0) && (255 == pImgData[searchIndex]) &&(!pLabelmap[searchIndex]))
    	{
    		pLabelmap[searchIndex] = labelIndex;
    		m_pNewBlob->nRight = m_pNewBlob->nRight>nCx+1?m_pNewBlob->nRight:nCx+1;
    		m_pNewBlob->nTop = m_pNewBlob->nTop<nCy-2?m_pNewBlob->nTop:nCy-2;
    		pEnd->nIndex = searchIndex;
    		pEnd->point.x = nCx+1;
    		pEnd->point.y = nCy-2;
    		pEnd++;
    	}
    
    	//  {-2,2}
    	searchIndex = pQueue->nIndex - 2 * m_nWidth + 2;
    	if ( (searchIndex>=0) && (nCx+2<m_nWidth) && (nCy-2>=0) && (255 == pImgData[searchIndex]) &&(!pLabelmap[searchIndex]))
    	{
    		pLabelmap[searchIndex] = labelIndex;
    		m_pNewBlob->nRight = m_pNewBlob->nRight>nCx+2?m_pNewBlob->nRight:nCx+2;
    		m_pNewBlob->nTop = m_pNewBlob->nTop<nCy-2?m_pNewBlob->nTop:nCy-2;
    		pEnd->nIndex = searchIndex;
    		pEnd->point.x = nCx+2;
    		pEnd->point.y = nCy-2;
    		pEnd++;
    	}
    
    	//  {-1,-2}
    	searchIndex = pQueue->nIndex - m_nWidth - 2;
    	if ( (searchIndex>=0) && (nCx-2>=0) && (nCy-1>=0) && (255 == pImgData[searchIndex]) &&(!pLabelmap[searchIndex]))
    	{
    		pLabelmap[searchIndex] = labelIndex;
    		m_pNewBlob->nLeft = m_pNewBlob->nLeft<nCx-2?m_pNewBlob->nLeft:nCx-2;
    		m_pNewBlob->nTop = m_pNewBlob->nTop<nCy-1?m_pNewBlob->nTop:nCy-1;
    		pEnd->nIndex = searchIndex;
    		pEnd->point.x = nCx-2;
    		pEnd->point.y = nCy-1;
    		pEnd++;
    	}
    
    	//  {-1,2}
    	searchIndex = pQueue->nIndex - m_nWidth + 2;
    	if ( (searchIndex>=0) && (nCx+2<m_nWidth) && (nCy-1>=0) && (255 == pImgData[searchIndex]) &&(!pLabelmap[searchIndex]))
    	{
    		pLabelmap[searchIndex] = labelIndex;
    		m_pNewBlob->nRight = m_pNewBlob->nRight>nCx+2?m_pNewBlob->nRight:nCx+2;
    		m_pNewBlob->nTop = m_pNewBlob->nTop<nCy-1?m_pNewBlob->nTop:nCy-1;
    		pEnd->nIndex = searchIndex;
    		pEnd->point.x = nCx+2;
    		pEnd->point.y = nCy-1;
    		pEnd++;
    	}
    
    	//  {0,-2}
    	searchIndex = pQueue->nIndex - 2;
    	if ( (searchIndex>=0) && (nCx-2>=0) && (255 == pImgData[searchIndex]) &&(!pLabelmap[searchIndex]))
    	{
    		pLabelmap[searchIndex] = labelIndex;
    		m_pNewBlob->nLeft = m_pNewBlob->nLeft<nCx-2?m_pNewBlob->nLeft:nCx-2;
    		pEnd->nIndex = searchIndex;
    		pEnd->point.x = nCx-2;
    		pEnd->point.y = nCy;
    		pEnd++;
    	}
    
    	//  {0,2}
    	searchIndex = pQueue->nIndex + 2;
    	if ( (searchIndex>=0) && (nCx+2<m_nWidth) && (255 == pImgData[searchIndex]) &&(!pLabelmap[searchIndex]))
    	{
    		pLabelmap[searchIndex] = labelIndex;
    		m_pNewBlob->nRight = m_pNewBlob->nRight>nCx+2?m_pNewBlob->nRight:nCx+2;
    		pEnd->nIndex = searchIndex;
    		pEnd->point.x = nCx+2;
    		pEnd->point.y = nCy;
    		pEnd++;
    	}
    
    	//  {1,-2}
    	searchIndex = pQueue->nIndex + m_nWidth - 2;
    	if ( (searchIndex>=0) && (nCx-2>=0) && (nCy+1<m_nHeight) && (255 == pImgData[searchIndex]) &&(!pLabelmap[searchIndex]))
    	{
    		pLabelmap[searchIndex] = labelIndex;
    		m_pNewBlob->nLeft = m_pNewBlob->nLeft<nCx-2?m_pNewBlob->nLeft:nCx-2;
    		m_pNewBlob->nBottom = m_pNewBlob->nBottom>nCy+1?m_pNewBlob->nBottom:nCy+1;
    		pEnd->nIndex = searchIndex;
    		pEnd->point.x = nCx-2;
    		pEnd->point.y = nCy+1;
    		pEnd++;
    	}
    
    	//  {1,2}
    	searchIndex = pQueue->nIndex + m_nWidth + 2;
    	if ( (searchIndex>=0) && (nCx+2<m_nWidth) && (nCy+1<m_nHeight) && (255 == pImgData[searchIndex]) &&(!pLabelmap[searchIndex]))
    	{
    		pLabelmap[searchIndex] = labelIndex;
    		m_pNewBlob->nRight = m_pNewBlob->nRight>nCx+2?m_pNewBlob->nRight:nCx+2;
    		m_pNewBlob->nBottom = m_pNewBlob->nBottom>nCy+1?m_pNewBlob->nBottom:nCy+1;
    		pEnd->nIndex = searchIndex;
    		pEnd->point.x = nCx+2;
    		pEnd->point.y = nCy+1;
    		pEnd++;
    	}
    
    	//  {2,-2}
    	searchIndex = pQueue->nIndex + 2 * m_nWidth - 2;
    	if ( (searchIndex>=0) && (nCx-2>=0) && (nCy+2<m_nHeight) && (255 == pImgData[searchIndex]) &&(!pLabelmap[searchIndex]))
    	{
    		pLabelmap[searchIndex] = labelIndex;
    		m_pNewBlob->nLeft = m_pNewBlob->nLeft<nCx-2?m_pNewBlob->nLeft:nCx-2;
    		m_pNewBlob->nBottom = m_pNewBlob->nBottom>nCy+2?m_pNewBlob->nBottom:nCy+2;
    		pEnd->nIndex = searchIndex;
    		pEnd->point.x = nCx-2;
    		pEnd->point.y = nCy+2;
    		pEnd++;
    	}
    
    	//  {2,-1}
    	searchIndex = pQueue->nIndex + 2 * m_nWidth - 1;
    	if ( (searchIndex>=0) && (nCx-1>=0) && (nCy+2<m_nHeight) && (255 == pImgData[searchIndex]) &&(!pLabelmap[searchIndex]))
    	{
    		pLabelmap[searchIndex] = labelIndex;
    		m_pNewBlob->nLeft = m_pNewBlob->nLeft<nCx-1?m_pNewBlob->nLeft:nCx-1;
    		m_pNewBlob->nBottom = m_pNewBlob->nBottom>nCy+2?m_pNewBlob->nBottom:nCy+2;
    		pEnd->nIndex = searchIndex;
    		pEnd->point.x = nCx-1;
    		pEnd->point.y = nCy+2;
    		pEnd++;
    	}
    
    	//  {2,0}
    	searchIndex = pQueue->nIndex + 2 * m_nWidth;
    	if ( (searchIndex>=0) && (nCy+2<m_nHeight) && (255 == pImgData[searchIndex]) &&(!pLabelmap[searchIndex]))
    	{
    		pLabelmap[searchIndex] = labelIndex;
    		m_pNewBlob->nBottom = m_pNewBlob->nBottom>nCy+2?m_pNewBlob->nBottom:nCy+2;
    		pEnd->nIndex = searchIndex;
    		pEnd->point.x = nCx;
    		pEnd->point.y = nCy+2;
    		pEnd++;
    	}
    
    	//  {-2,1}
    	searchIndex = pQueue->nIndex + 2 * m_nWidth + 1;
    	if ( (searchIndex>=0) && (nCx+1<m_nWidth) && (nCy+2<m_nHeight) && (255 == pImgData[searchIndex]) &&(!pLabelmap[searchIndex]))
    	{
    		pLabelmap[searchIndex] = labelIndex;
    		m_pNewBlob->nRight = m_pNewBlob->nRight>nCx+1?m_pNewBlob->nRight:nCx+1;
    		m_pNewBlob->nBottom = m_pNewBlob->nBottom>nCy+2?m_pNewBlob->nBottom:nCy+2;
    		pEnd->nIndex = searchIndex;
    		pEnd->point.x = nCx+1;
    		pEnd->point.y = nCy+2;
    		pEnd++;
    	}
    
    	//  {-2,2}
    	searchIndex = pQueue->nIndex + 2 * m_nWidth + 2;
    	if ( (searchIndex>=0) && (nCx+2<m_nWidth) && (nCy+2<m_nHeight) && (255 == pImgData[searchIndex]) &&(!pLabelmap[searchIndex]))
    	{
    		pLabelmap[searchIndex] = labelIndex;
    		m_pNewBlob->nRight = m_pNewBlob->nRight>nCx+2?m_pNewBlob->nRight:nCx+2;
    		m_pNewBlob->nBottom = m_pNewBlob->nBottom>nCy+2?m_pNewBlob->nBottom:nCy+2;
    		pEnd->nIndex = searchIndex;
    		pEnd->point.x = nCx+2;
    		pEnd->point.y = nCy+2;
    		pEnd++;
    	}
    }
    /************************************************************************/
    /*                                                          */
    /************************************************************************/
    int	CombineBlob(int nNum, IVT_BLOB *pBlob)
    {
    	int			i=0,nFlag,j,k=0;
    	IVT_RECT	*p1,*p2;
    	IVT_BLOB	*pB1;
    	if (nNum<2||pBlob==NULL)
    	{
    		return nNum;
    	}
    	for (i=0;i<nNum; i++,k=0)
    	{
    		p1 = &pBlob[i].BlobRect;
    		for (;k<nNum; k++)
    		{
    			if (i!=k)
    			{
    				p2 = &pBlob[k].BlobRect;
    				nFlag = RectsIfMerge(p1,p2);
    				if (nFlag == 1)
    				{
    					if (k>i)
    					{
    						for (j=k;j<nNum-1;j++)
    						{
    							pBlob[j] = pBlob[j+1];
    						}
    					}
    					else
    					{
    						for (j=k;j<nNum-1;j++)
    						{
    							pBlob[j] = pBlob[j+1];
    						}
    						i--;
    						p1 = &pBlob[i].BlobRect;
    					}
    					nNum--;
    					k = -1;
    				}
    
    			}
    		}
    	}
    	return nNum;
    }
    /************************************************************************/
    /*           
       1—— 
       0—— */
    /************************************************************************/
    int RectsIfMerge(IVT_RECT *ptRectI,	IVT_RECT *pRectJ)
    {
    	int		x1, y1, x11, y11, x2, y2, x22, y22,Wi, Hi,Wj, Hj,Ow, Oh,Uw, Uh;  
    	int		nCenter_x1,nCenter_y1,nCenter_x2,nCenter_y2,nIndex1,nIndex2,nLocation1,nLocation2,nIndexMin;
    	int		nMax_X,nMax_Y,nMin_X,nMin_Y;
    
    	nCenter_x1 = (ptRectI->nLeft+ptRectI->nRight)>>1;
    	nCenter_y1 = (ptRectI->nTop+ptRectI->nBottom)>>1;
    	nIndex1 = nCenter_y1*m_nWidth+nCenter_x1;
    	nLocation1 = m_pImageROI_Data[nIndex1].nIndex;
    
    	nCenter_x2 = (pRectJ->nLeft+pRectJ->nRight)>>1;
    	nCenter_y2 = (pRectJ->nTop+pRectJ->nBottom)>>1;
    	nIndex2 = nCenter_y2*m_nWidth+nCenter_x2;
    	nLocation2 = m_pImageROI_Data[nIndex2].nIndex;
    
    	if (abs(nLocation1-nLocation2)>1)
    	{
    		return 0;
    	}
    	nIndexMin = nLocation1<nLocation2?nLocation1:nLocation2;
    
    	x1  = ptRectI->nLeft;
    	y1  = ptRectI->nTop;
    	x11 = ptRectI->nRight;
    	y11 = ptRectI->nBottom; 
    
    	x2  = pRectJ->nLeft;
    	y2  = pRectJ->nTop;
    	x22 = pRectJ->nRight;
    	y22 = pRectJ->nBottom;
    
    	nMax_X = MaxInt(x11, x22);
    	nMin_X = MinInt(x1, x2);
    	nMax_Y = MaxInt(y11, y22);
    	nMin_Y = MinInt(y1, y2);
    
    	if ((((y2<y11)&&(y1<y2))||((y22<y11)&&(y22>y1)))
    		&&(((x2<x11)&&(x1<x2))||((x22<x11)&&(x1<x22))))
    	{
    		ptRectI->nLeft = nMin_X;
    		ptRectI->nTop = nMin_Y;
    		ptRectI->nRight = nMax_X;
    		ptRectI->nBottom = nMax_Y; 
    		return 1;
    	}
    	if (((y1<y22)&&(y2<y1)||(y11<y22)&&(y11>y2))
    		&&((x1<x22)&&(x1>x2)||(x22>x11)&&(x2<x11)))
    	{
    		ptRectI->nLeft = nMin_X;
    		ptRectI->nTop = nMin_Y;
    		ptRectI->nRight = nMax_X;
    		ptRectI->nBottom = nMax_Y; 
    		return 1;
    	}  
    	Wi = x11 - x1;
    	Hi = y11 - y1;
    
    	Wj = x22 - x2;
    	Hj = y22 - y2;
    
    	Uw = nMax_X - nMin_X;
    	Uh = nMax_Y - nMin_Y;
    	Ow = Uw - Wi - Wj;
    	Oh = Uh - Hi - Hj;
    
    	if((Ow<Trow[nIndexMin])&&(Oh<Troh[nIndexMin]))
    	{
    		ptRectI->nLeft = nMin_X;
    		ptRectI->nTop = nMin_Y;
    		ptRectI->nRight = nMax_X;
    		ptRectI->nBottom = nMax_Y; 
    		return 1;
    	}
    
    	return 0;  
    }
    int	MaxInt(int n, int m)
    {
    	return m>n?m:n;
    }
    int MinInt(int n, int m)
    {
    	return m<n?m:n;
    }