00001 /*---------------------------------------------------------------------+ 00002 | Library QgarLib, graphics analysis and recognition | 00003 | Copyright (C) 2002 Qgar Project, LORIA | 00004 | | 00005 | This library is free software; you can redistribute it and/or | 00006 | modify it under the terms of the GNU Lesser General Public | 00007 | License version 2.1, as published by the Free Software Foundation. | 00008 | | 00009 | This library is distributed in the hope that it will be useful, | 00010 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 00011 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | 00012 | See the GNU Lesser General Public License for more details. | 00013 | | 00014 | The GNU Lesser General Public License is included in the file | 00015 | LICENSE.LGPL, in the root directory of the Qgar packaging. See | 00016 | http://www.gnu.org/licenses/lgpl.html for the terms of the licence. | 00017 | To receive a paper copy, write to the Free Software Foundation, | 00018 | Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. | 00019 | | 00020 | Contact Project Qgar for any information: | 00021 | LORIA - équipe Qgar | 00022 | B.P. 239, 54506 Vandoeuvre-lès-Nancy Cedex, France | 00023 | email: qgar-contact@loria.fr | 00024 | http://www.qgar.org/ | 00025 *---------------------------------------------------------------------*/ 00026 00027 00028 /** 00029 * @file ConnectedComponents.C 00030 * @brief Implementation of class qgar::ConnectedComponents. 00031 * 00032 * See file ConnectedComponents.H for the interface. 00033 * 00034 * @author <a href="mailto:qgar-develop@loria.fr?subject=Qgar fwd Gérald Masini">Gérald Masini</a> 00035 * @date April 21, 2004 12:58 00036 * @since Qgar 2.1.1 00037 */ 00038 00039 00040 // STL 00041 #include <deque> 00042 #include <list> 00043 #include <vector> 00044 // QGAR 00045 #include <qgarlib/Component.H> 00046 #include <qgarlib/ConnectedComponents.H> 00047 #include <qgarlib/ConnectedComponentsImpl.H> 00048 #include <qgarlib/GenImage.H> 00049 00050 00051 00052 namespace qgar 00053 { 00054 00055 // ------------------------------------------------------------------- 00056 // ------------------------------------------------------------------- 00057 // C O N S T R U C T O R S 00058 // ------------------------------------------------------------------- 00059 // ------------------------------------------------------------------- 00060 00061 00062 // CONSTRUCT FROM GIVEN BINARY IMAGE 00063 00064 ConnectedComponents::ConnectedComponents(const BinaryImage& aBinImg) 00065 00066 : _componentImg(ConnectedComponents::image_type(aBinImg.width(), 00067 aBinImg.height())) 00068 00069 { 00070 // Initialize data in order to run the construction of components 00071 ConnectedComponentsImpl ccImpl(aBinImg, 00072 &_componentImg, 00073 _componentTree, 00074 _componentTab); 00075 00076 // Run the construction of connected components 00077 ccImpl.run(); 00078 } 00079 00080 00081 // COPY CONSTRUCTOR 00082 // WARNING: Perform a deep copy 00083 00084 ConnectedComponents::ConnectedComponents(const ConnectedComponents& aCC) 00085 00086 : _componentImg(aCC._componentImg), 00087 _componentTree(aCC._componentTree), 00088 _componentTab((aCC._componentTab).size(), 0) 00089 00090 { 00091 // Components are not duplicated as data stored in tree nodes 00092 // are pointers to components 00093 // => effective duplication of components 00094 // and subsequent updating of the component table 00095 00096 PRIVATEcopyCC((aCC._componentTree).pRoot(), _componentTree.pRoot()); 00097 } 00098 00099 00100 // ------------------------------------------------------------------- 00101 // ------------------------------------------------------------------- 00102 // D E S T R U C T O R 00103 // ------------------------------------------------------------------- 00104 // ------------------------------------------------------------------- 00105 00106 00107 ConnectedComponents::~ConnectedComponents() 00108 { 00109 // Delete components 00110 00111 for(std::vector<ConnectedComponents::node_type*>::iterator itN 00112 = _componentTab.begin(); 00113 itN != _componentTab.end(); 00114 ++itN) 00115 { 00116 delete (*itN)->data(); 00117 } 00118 } 00119 00120 00121 // ------------------------------------------------------------------- 00122 // ------------------------------------------------------------------- 00123 // R E C O N S T R U C T B I N A R Y I M A G E S 00124 // ------------------------------------------------------------------- 00125 // ------------------------------------------------------------------- 00126 00127 00128 // RECONSTRUCT A BINARY IMAGE FROM GIVEN LABELS 00129 // A pixel of the resulting image is BLACK if it belongs to a black 00130 // component whose label is in the set of given labels. 00131 // Given labels out of the range of current labels are ignored. 00132 00133 BinaryImage* 00134 ConnectedComponents::makeBinaryImg 00135 (const std::vector<Component::label_type>& aLabSet) 00136 { 00137 // Create the resulting image 00138 BinaryImage* pImgBin = new BinaryImage(_componentImg.width(), 00139 _componentImg.height()); 00140 00141 // Pointers to pixels maps 00142 Component::label_type* pMapCC = _componentImg.pPixMap(); 00143 BinaryImage::value_type* pMapBin = pImgBin->pPixMap(); 00144 00145 // Current label and color 00146 Component::label_type currLab = Component::_NO_LABEL; 00147 QGEbw currColor; 00148 00149 // Number of pixels of both images 00150 int size = _componentImg.width() * _componentImg.height(); 00151 00152 // For each pixel of the component image 00153 00154 for (int iCnt = 0 ; iCnt< size ; ++iCnt, ++pMapCC, ++pMapBin) 00155 { 00156 if (*pMapCC != currLab) 00157 { 00158 // The new pixel belongs to a new component 00159 00160 currLab = *pMapCC; 00161 00162 std::vector<Component::label_type>::const_iterator it = 00163 find(aLabSet.begin(), aLabSet.end(), currLab); 00164 00165 if ( (it == aLabSet.end()) 00166 || ((*this)[currLab].color() == QGE_BW_WHITE)) 00167 { 00168 // Current label does not belong to the given set 00169 // or belongs to a WHITE component 00170 currColor = QGE_BW_WHITE; 00171 } 00172 else 00173 { 00174 // Current label belongs to a BLACK component 00175 currColor = QGE_BW_BLACK; 00176 } 00177 } 00178 00179 // Set the corresponding pixel of the resulting image 00180 // to current color 00181 *pMapBin = currColor; 00182 } 00183 00184 // Return a pointer to the resulting image 00185 return pImgBin; 00186 } 00187 00188 00189 // ------------------------------------------------------------------- 00190 // ------------------------------------------------------------------- 00191 // O P E R A T O R S 00192 // ------------------------------------------------------------------- 00193 // ------------------------------------------------------------------- 00194 00195 00196 // ASSIGNMENT 00197 00198 ConnectedComponents& 00199 ConnectedComponents::operator=(const ConnectedComponents& aCC) 00200 { 00201 // Are left hand side and right hand side different objects? 00202 if (this != &aCC) 00203 { 00204 // Copy component tree and component table 00205 _componentImg = aCC._componentImg; 00206 _componentTree = aCC._componentTree; 00207 _componentTab = aCC._componentTab; 00208 00209 // The tree of the given CC image is duplicated, but the data 00210 // pointed by nodes (i.e. components) are not 00211 00212 // Effective duplication of components 00213 // and subsequent updating of the component table 00214 PRIVATEcopyCC((aCC._componentTree).pRoot(), 00215 _componentTree.pRoot()); 00216 } 00217 00218 return *this; 00219 } 00220 00221 00222 // ------------------------------------------------------------------- 00223 // ------------------------------------------------------------------- 00224 // A U X I L I A R I E S 00225 // ------------------------------------------------------------------- 00226 // ------------------------------------------------------------------- 00227 00228 // Copy components stored in tree whose root is node IN 00229 // and store them in corresponding nodes of tree whose root is node OUT. 00230 // WARNING: Both trees must have the same structure (the tree including 00231 // node OUT is supposed to be a copy of the tree including node IN). 00232 00233 void 00234 ConnectedComponents::PRIVATEcopyCC(ConnectedComponents::node_type* aPNodeIn, 00235 ConnectedComponents::node_type* aPNodeOut) 00236 { 00237 if (aPNodeIn != 0) 00238 { 00239 // Copy current component 00240 Component* cc = new Component(*(aPNodeIn->data())); 00241 00242 // Store copy and update component table 00243 aPNodeOut->setData(cc); 00244 _componentTab[cc->label()] = aPNodeOut; 00245 00246 // Copy children and siblings 00247 PRIVATEcopyCC(aPNodeIn->pFirstChild(), aPNodeOut->pFirstChild()); 00248 PRIVATEcopyCC(aPNodeIn->pRSibling(), aPNodeOut->pRSibling()); 00249 } 00250 } 00251 00252 // ------------------------------------------------------------------- 00253 // ------------------------------------------------------------------- 00254 00255 } // namespace qgar