/******************************************************************** ** Image Component Library (ICL) ** ** ** ** Copyright (C) 2006-2010 CITEC, University of Bielefeld ** ** Neuroinformatics Group ** ** Website: www.iclcv.org and ** ** http://opensource.cit-ec.de/projects/icl ** ** ** ** File : ICLFilter/src/ColorSegmentationOp.cpp ** ** Module : ICLFilter ** ** Authors: Christof Elbrechter ** ** ** ** ** ** Commercial License ** ** ICL can be used commercially, please refer to our website ** ** www.iclcv.org for more details. ** ** ** ** GNU General Public License Usage ** ** Alternatively, this file may be used under the terms of the ** ** GNU General Public License version 3.0 as published by the ** ** Free Software Foundation and appearing in the file LICENSE.GPL ** ** included in the packaging of this file. Please review the ** ** following information to ensure the GNU General Public License ** ** version 3.0 requirements will be met: ** ** http://www.gnu.org/copyleft/gpl.html. ** ** ** ** The development of this software was supported by the ** ** Excellence Cluster EXC 277 Cognitive Interaction Technology. ** ** The Excellence Cluster EXC 277 is a grant of the Deutsche ** ** Forschungsgemeinschaft (DFG) in the context of the German ** ** Excellence Initiative. ** ** ** *********************************************************************/ #include #include #include #include #include #include namespace icl{ struct ColorSegmentationOp::LUT3D : public Uncopyable{ int dim, w, h,t, wh; icl8u *data; mutable Img8u image; LUT3D(int w, int h, int t): dim(w*h*t),w(w),h(h),t(t),wh(w*h),data(dim ? new icl8u[dim] : 0){ } ~LUT3D(){ ICL_DELETE_ARRAY(data); } inline icl8u &operator()(int x, int y, int z){ return data[x+w*y+wh*z]; } inline const icl8u &operator()(int x, int y, int z) const{ return data[x+w*y+wh*z]; } void resize(int w, int h, int t){ if(w*h*t != dim){ ICL_DELETE_ARRAY(data); dim = w*h*t; wh = w*h; this->w = w; this->h = h; this->t = t; data = dim ? new icl8u[dim] : 0; } } void clear(icl8u value) { std::fill(data,data+dim,value); } void save(const std::string &filename){ std::vector datas(t); for(int i=0;iasImg(); ICLASSERT_THROW(image.getWidth() == w && image.getHeight() == h && image.getChannels() == t, ICLException("invalid lut dimensions")); for(int i=0;i= 0 && zSlice < t,ICLException("invalid zSlice value")); const int dims[3]={w,h,t}; int w = dims[xDim]; int h = dims[yDim]; image.setSize(Size(w,h)); image.setChannels(1); Channel8u cim = image[0]; if(xDim == 0){ if(yDim == 0){ std::copy(data+wh*zSlice,data+(wh+1)*zSlice,image.begin(0)); }else{ #define IMPL_XY_LOOP(X,Y,Z) \ for(int x=0;x struct ShiftedLUT3D_T{ const ColorSegmentationOp::LUT3D &lut; ShiftedLUT3D_T(const ColorSegmentationOp::LUT3D &lut):lut(lut){} inline const icl8u &operator()(int x, int y, int z) const{ return lut(x>>xShift,y>>yShift,z>>zShift); } }; struct ShiftedLUT3D{ int xShift,yShift,zShift; ColorSegmentationOp::LUT3D &lut; ShiftedLUT3D(int xShift, int yShift, int zShift, ColorSegmentationOp::LUT3D &lut): xShift(xShift),yShift(yShift),zShift(zShift),lut(lut){} ShiftedLUT3D(const icl8u *shifts, ColorSegmentationOp::LUT3D &lut): xShift(shifts[0]),yShift(shifts[1]),zShift(shifts[2]),lut(lut){} void resize(){ lut.resize((0xFF>>xShift)+1,(0xFF>>yShift)+1,(0xFF>>zShift)+1); } inline icl8u &operator()(int x, int y, int z){ return lut(x>>xShift,y>>yShift,z>>zShift); } inline const icl8u &operator()(int x, int y, int z) const{ return lut(x>>xShift,y>>yShift,z>>zShift); } }; template static void apply_lookup(SrcIterator a, SrcIterator b, SrcIterator c, DstIterator d, DstIterator dEnd, const ShiftedLUT3D_T &lut){ while(d!=dEnd){ *d = lut(*a,*b,*c); ++a; ++b; ++c; ++d; } } ColorSegmentationOp::ColorSegmentationOp(icl8u c0shift, icl8u c1shift, icl8u c2shift, format fmt) throw (ICLException): m_segFormat(fmt),m_lut(new LUT3D(0,0,0)){ ICLASSERT_THROW(getChannelsOfFormat(fmt) == 3,ICLException("Construktor ColorSegmentationOp: format must be a 3-channel format")); setSegmentationShifts(c0shift,c1shift,c2shift); } ColorSegmentationOp::~ColorSegmentationOp(){ ICL_DELETE(m_lut); } void ColorSegmentationOp::apply(const ImgBase *src, ImgBase **dst){ ICLASSERT_THROW(src,ICLException("ColorSegmentationOp::apply: source must not be null")); ICLASSERT_THROW(src->hasFullROI(), ICLException("ColorSegmentationOp::apply: source image has a ROI which is not supported yet!")); // preparing destination image if(!dst) dst = bpp(m_outputBuffer); if(getClipToROI()){ bool ok = prepare(dst,depth8u,src->getROISize(),formatMatrix,1,Rect(Point::null,src->getROISize()),src->getTime()); ICLASSERT_THROW(ok,ICLException("ColorSegmentationOp::apply: unable to prepare destination image")); }else{ bool ok = prepare(dst,depth8u,src->getSize(),formatMatrix,1,src->getROI(),src->getTime()); ICLASSERT_THROW(ok,ICLException("ColorSegmentationOp::apply: unable to prepare destination image")); } Img8u &dstRef = *(*dst)->asImg(); // preparing source image if(src->getFormat() != m_segFormat || src->getDepth() != depth8u){ m_inputBuffer.setFormat(m_segFormat); cc(src,&m_inputBuffer); src = &m_inputBuffer; } const Img8u &srcRef = *src->asImg(); // we use cross-instantiated templates for better performance #define SHIFT_2_CASE(SH0,SH1,SH2) \ case SH2: apply_lookup(srcRef.begin(0),srcRef.begin(1),srcRef.begin(2), \ dstRef.begin(0),dstRef.end(0),ShiftedLUT3D_T(*m_lut)); break #define SHIFT_2(SH0,SH1) \ switch(m_bitShifts[2]){ \ SHIFT_2_CASE(SH0,SH1,0); SHIFT_2_CASE(SH0,SH1,1); \ SHIFT_2_CASE(SH0,SH1,2); SHIFT_2_CASE(SH0,SH1,3); \ SHIFT_2_CASE(SH0,SH1,4); SHIFT_2_CASE(SH0,SH1,5); \ SHIFT_2_CASE(SH0,SH1,6); SHIFT_2_CASE(SH0,SH1,7); \ default: apply_lookup(srcRef.begin(0), \ srcRef.begin(1), \ srcRef.begin(2), \ dstRef.begin(0), \ dstRef.end(0), \ ShiftedLUT3D_T(*m_lut)); break; \ } #define SHIFT_1_CASE(SH0,SH1) \ case SH1: SHIFT_2(SH0,SH1) break; #define SHIFT_1(SH0) \ switch(m_bitShifts[1]){ \ SHIFT_1_CASE(SH0,0);SHIFT_1_CASE(SH0,1); \ SHIFT_1_CASE(SH0,2);SHIFT_1_CASE(SH0,3); \ SHIFT_1_CASE(SH0,4);SHIFT_1_CASE(SH0,5); \ SHIFT_1_CASE(SH0,6);SHIFT_1_CASE(SH0,7); \ default: SHIFT_2(SH0,8); break; \ } switch(m_bitShifts[0]){ #define SHIFT_0_CASE(SH0) case SH0: SHIFT_1(SH0); break SHIFT_0_CASE(0); SHIFT_0_CASE(1); SHIFT_0_CASE(2); SHIFT_0_CASE(3); SHIFT_0_CASE(4); SHIFT_0_CASE(5); SHIFT_0_CASE(6); SHIFT_0_CASE(7); default: SHIFT_1(8); break; } } const Img8u &ColorSegmentationOp::getSegmentationPreview(){ TODO_LOG("implemenent ColorSegmentationOp::getSegmentationPreview"); return m_segPreview; } void ColorSegmentationOp::setSegmentationFormat(format fmt) throw (ICLException){ ICLASSERT_THROW(getChannelsOfFormat(fmt) == 3, ICLException("ColorSegmentationOp::setSegmentationFormat: Segmentation format must have 3 channels")); m_segFormat = fmt; } void ColorSegmentationOp::setSegmentationShifts(icl8u c0shift, icl8u c1shift, icl8u c2shift){ m_bitShifts[0] = c0shift; m_bitShifts[1] = c1shift; m_bitShifts[2] = c2shift; ShiftedLUT3D lut(m_bitShifts,*m_lut); lut.resize(); } void ColorSegmentationOp::lutEntry(icl8u a, icl8u b, icl8u c, icl8u rA, icl8u rB, icl8u rC, icl8u value){ const int sa = pow(2, m_bitShifts[0]); const int sb = pow(2, m_bitShifts[1]); const int sc = pow(2, m_bitShifts[2]); ShiftedLUT3D lut(m_bitShifts,*m_lut); for(int ia=a-rA; ia<=a+rA; ia+=sa){ //if(ia < 0) continue; //else if(ia > 255) break; for(int ib=b-rB; ib<=b+rB; ib+=sb){ //if(ib < 0) continue; //else if(ib > 255); break; for(int ic=c-rC; ic<=c+rC; ic+=sc){ //if(ic < 0) continue; //else if(ic > 255) break; if(ia >= 0 && ia < 256 && ib >= 0 && ib < 256 && ic >= 0 && ic < 256){ lut(ia,ib,ic) = value; } } } } } void ColorSegmentationOp::lutEntry(format fmt, int a, int b, int c, int rA, int rB, int rC, icl8u value) throw (ICLException){ if(fmt == m_segFormat) lutEntry(a,b,c,rA,rB,rC,value); ICLASSERT_THROW(getChannelsOfFormat(fmt) == 3, ICLException("ColorSegmentationOp::lutEntry format must have 3 channels")); Img8u src(Size(1,1),fmt),dst(Size(1,1),m_segFormat); src(0,0).set(a,b,c); cc(&src,&dst); //DEBUG_LOG("adding color: Y:" << (int)dst(0,0,0) << " U:" << (int)dst(0,0,1) << " V:" << (int)dst(0,0,2)); lutEntry(dst(0,0,0),dst(0,0,1),dst(0,0,2),rA,rB,rC,value); } void ColorSegmentationOp::clearLUT(icl8u value){ m_lut->clear(value); } const Img8u &ColorSegmentationOp::getLUTPreview(int xDim, int yDim, icl8u zValue){ return m_lut->getImage(xDim,yDim,zValue>>m_bitShifts[2]); } void ColorSegmentationOp::load(const std::string &filename){ try{ m_lut->load(filename); }catch(ICLException &ex){ ERROR_LOG(ex.what()); } } void ColorSegmentationOp::save(const std::string &filename) { m_lut->save(filename); } }