From 3b2c8a9b849ca7f380df4cce8d25cdcf82464c54 Mon Sep 17 00:00:00 2001 From: Julien Lengrand-Lambert Date: Mon, 19 Dec 2011 14:40:58 +0100 Subject: [PATCH] Adds histogram support to 3 channels images Finishes support for 3 channels images. Adds a function allowing to extract only one desired channel Updates the example to extract all channels. Support for 16 and 32 bits images should be tested. Function for 3c to 1c to be added quickly! Reported-by: Julien Lengrand-Lambert Signed-off-by: Julien Lengrand-Lambert --- bin/__init__.pyc | Bin 0 -> 128 bytes examples/__init__.pyc | Bin 0 -> 133 bytes examples/histogram_display.py | 22 ++-- examples/region_growing.pyc | Bin 0 -> 2602 bytes tippy/__init__.pyc | Bin 0 -> 130 bytes tippy/basic_operations.pyc | Bin 0 -> 3724 bytes tippy/display_operations.pyc | Bin 0 -> 1426 bytes tippy/segmentations.pyc | Bin 0 -> 3512 bytes tippy/statistics.py | 129 ++++++++++++++++++------ tippy/statistics.pyc | Bin 0 -> 6455 bytes tippy/tests/__init__.pyc | Bin 0 -> 136 bytes tippy/tests/test_basic_operations.pyc | Bin 0 -> 3238 bytes tippy/tests/test_display_operations.pyc | Bin 0 -> 2166 bytes tippy/tests/test_segmentation.pyc | Bin 0 -> 4765 bytes tippy/tests/test_statistics.py | 80 ++++++++++----- tippy/tests/test_statistics.pyc | Bin 0 -> 6896 bytes 16 files changed, 160 insertions(+), 71 deletions(-) create mode 100644 bin/__init__.pyc create mode 100644 examples/__init__.pyc create mode 100644 examples/region_growing.pyc create mode 100644 tippy/__init__.pyc create mode 100644 tippy/basic_operations.pyc create mode 100644 tippy/display_operations.pyc create mode 100644 tippy/segmentations.pyc create mode 100644 tippy/statistics.pyc create mode 100644 tippy/tests/__init__.pyc create mode 100644 tippy/tests/test_basic_operations.pyc create mode 100644 tippy/tests/test_display_operations.pyc create mode 100644 tippy/tests/test_segmentation.pyc create mode 100644 tippy/tests/test_statistics.pyc diff --git a/bin/__init__.pyc b/bin/__init__.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6875fb8d3892e7f9c2d38cd62fcf35010eb5dd0c GIT binary patch literal 128 zcmZSn%*$1G^{!ts0~9a)fQ%ZAE?LcN012F>t!SWhY literal 0 HcmV?d00001 diff --git a/examples/__init__.pyc b/examples/__init__.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f7fa6096f52d8427e84973faaef2f4b18b61daf2 GIT binary patch literal 133 zcmZSn%*$1G^{!ts0~9a3XpXA~$mZ$6kwG6vZ$kYr8Z2^PNL_>#x0NwDtKsVa?|n?nn4{f8vrdHpI2X z(l*mAHpD~y+-B1)Hr!qgud!)|4X-bUH`w$h8%8X}J3B1hX2V^UUSq>Omg2QrOt#qc zHj}&I;ST%MX2ZKo?y&L?Ca<&UJtpt66y9#IPp#JQJ~JJb?lL^cZ8m*Cs}j$9Ox|Lj z;C!FSh)o|dxzExa^43DS7u`Lo;&X?w=w&H|mnpY~pW7LK`n<=Ve*5G}6dj4mPi*;u z|5Rxu4L_46D}_l9&qO|wrH_teE|h-3r(yj_H|zaz866%TMsH*(xpG`^r}9EeEm_RioT8^sCogT$9Z0;)j)hLo9cDwP9po$kw$6PqJ_E-OsLF{Y-BQq|vzrYFq|lM{ zbBSIr+YuD;4Y+N*M5FwI&xEdE6!x2CyYNCTg(0~@5ws!H89`wxuV{N)S~s$2Xtm6i zk|km^se;Rp9Ci#{L3MQ%%iYU?TaW>?X~7NLLCwtq;04^zf}p`Jf%Q^C#~Oa3=#*56 zSFY}o;01qnm{_P3jF?fC6L=mG5Oqp*4$rT?v)&z+sfMHw=M@lY_KK#_=#A9l9(oOW z;$T@g@DeqWECHT?hE{tCT0e$Jjh*-T1vXr(F>2mi$3(giF`Z>&RXWHuiqzluoGTo5 z%-zGqtD;y8Xs;P$rs_|NOg+G~xz@X3Er_^bc|a8sjFFV5mMts6F`8+KX~gbgo~&zq0ld~kqW}N^ literal 0 HcmV?d00001 diff --git a/tippy/__init__.pyc b/tippy/__init__.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8ec2d8d55d9356df1e1f0af1edb9755c9caaf997 GIT binary patch literal 130 zcmZSn%*$1G^{!ts0~9a&ryk0?N2?tQUO>TZlX-=vg$kbvWW&i*QxEoRc literal 0 HcmV?d00001 diff --git a/tippy/basic_operations.pyc b/tippy/basic_operations.pyc new file mode 100644 index 0000000000000000000000000000000000000000..266cac8b9debfcd129a8b2d874f6d550cabad8e5 GIT binary patch literal 3724 zcmcIn&vP3|748{1vOS5{*=*Q?VyX0+U65H>PQnS-hKfaOKE}KY6bZO-52#nN8GC z%cRnZCYmxa<-93d^cQuEJml%JGKsb}D~6b#l)1iy(4na^H=0;E(v@z>C~A`sok~;4 zj+w~^KWoZ|_a8inqQ`3LMyA@6zntcoF65CehLtMPog+0l)0K-J>xs(pJvrw2$N6Hu zHK?NOU-)#A8?cBTg0hXrZlifAgcD*Mi1ScX9}5?XaZS7o#LG|&Lh&jPLBUA(8X;}@ z6Pifk(=mmXkD%wVnOfb@GhMi*ylhHXKFHM&@RX`jlkJF?f3`qP!VEJ3P6-g5OKM^5 z*<6}Z7s*Usj9}YH%?PFmNtP_x5+F*ls5G->uIAV_fPA2Kh#i2hDKE5Cm6lekDjAW4 zfvK=7*8{f@mgHG-?)7i1z!aD(L^5-C@zs72AG|o|^y8ynJn#3Pb)Gys>9`0JF)I?6 z#=1IQRS8wo1|jLFVFg`)-X*tl9%T%;$1pT7Ex55iMQ?XxCVF?gyrkV>=63s8Sh8Wky`?&W%1_C!vtHb5$-|=d^e&gy@Fx9T0RoslUji|cx{uX8x%L&;005qSpfn7;lPnA z?Wzp!mHM5$y?Pu4gs}YE}8f2Aq zULAiBZR~0{t%&$!p3$r)LJFz}66!)*HwB6L4Lirv9F9vzvmzv5AB@Q+dRwd_JN`=_ z3xzo52_=Tm%}W>uwa)eY%&028lDJgqnl9Hgu?tmpc6h_VrB@}J3_(-LtaW5m%1qqY zYPEJ#<&=-L*0>yQfwN~V5Wvy1{U`C^@&40;_-S|lx4riM(ZM#$TXFz}R|7(uvHMhx-JA`m)psSpLH|^T*itHS<4M?k6+$ z?0a%ZoEz^y??3Auo*p1xu~|DNwl)&QnM%&P#Dc6qZ)7eQ z47Y)y*jopZ#s%@tcxj;@vuxrEl}{JO(5@#MMw+=-qf5D|*k}=$&tNj*e zoQ%KbOynWLM>#``_IXX5fJb|r^Xz@>VV^!MoURI$Uok|JLNEo%`E==#X0X z;}a+0g!ILr`MajeKLH*7O3&ZG^j0aa`(23q43E!rE8p<|P^!HGpoteGurC3_Jt}6< zCjfrDsA@a_nEibHts$T)Y5@Tq&sKLoM6W>_v5zDpRlPC(e@*q>??K)%9!vFxSgFG; z_yQ6-myo~8=oMZ7H|`%L9JL{VfICM^g&bPs^_uuH6h65kFCw{~aB@X4j7@bhUZos~ z%#D=&KK4@Tr{o%ls$iiJrBrexR0QZPYC)26X(l-VWH?cPDdE_n(lJ*$y3Wd$kB6NE7{ zwwXE_e0#rTx@X(;H6)(nSWD`Ns21D_>cMU1HGGE+W^*zzj#HDwvA2TOdSapZ?mcRV t3OFvhpP=_f*S8`Vw+30Cg4n0I{yCjx3BWoy_f}XB*Kclqvc9^$_HPy8qHzEK literal 0 HcmV?d00001 diff --git a/tippy/display_operations.pyc b/tippy/display_operations.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fa0ad1f1c41e593d25e84a8b91e13b9048704b64 GIT binary patch literal 1426 zcmbtUUvJws5I@OD+N$x|tz9vo59I<3Z~<3N1`I`mbx7a@MK;G9;-E$IP=OU`nTA9P zhv-{J92aB#B|t+wcMYB9aV^My|ADye!#tp>tG*c2<@g zrC?}SVR=1MIWL(|t}c0#Cdtsspf;L~%{kk7)@R>u@9ZSW9$(7QV|2W-}>oO9@2Clh#B2d+A;XfuewpB+rPa7jrn?Y~$#6I7Gln!jEV5h{$vL0fG?Ml z!Km6Uw^Hgf82o0O@@TP~EZ$0%&y170PxgeHsy?wN7)|SQK)5z6H`Yp58!eni7-w>Y zZE)-}rCFuQQaPD>qt^Fm%0zH~zTFQ#0VU>;H|{z&w$P|bws6u?7?hTWmTE&hp%HRF zyx0w^stWd;<>%?ha1rA5w$gMUIPw9ix^B{WU2OHe#qeb|`gQ*xJ38KfahSb0*?&D5 z?vD;1hd9gD%$(9iDYHcEB`bZRo@}_TRd%JaV52@h2@7!ZH=2WiT30iVz z@}ibGHUGEntCjvpnf78If=Wi+OtN$Ql9mZ_i?5Ux=H2Ox9-YA3B=zZvRvOYcHs^A= z^~X(@hx8My{u$Y?qApEnWb%XcGbEWwdFrT6Oh6r@;M317o;rA#` zqHc7L_-+(lNVrs%36p2piO>4P-}&TgBG=jd-xP0Bv>z)Y7Nz{j^Ug!I5pPDD@xM1q BY%%}< literal 0 HcmV?d00001 diff --git a/tippy/segmentations.pyc b/tippy/segmentations.pyc new file mode 100644 index 0000000000000000000000000000000000000000..87f7ef7400a27ceba0082b4c558d50313e136c2c GIT binary patch literal 3512 zcmbVPOLH5?5$@duU!W*ie2Anio5M<+KxK-QRC3Hxq?8g$WizExR3sgxSY@M@m;o># zunX-BNFoLJ5akEtlv7T*=8}8v4h^8?ysNQJBO74(Jd>PKR_Dj_8OEBhvVmNKer3u>~Te{mLZ6 z`~ge(plO}z7~f2_s-=mKZQ@kiZmW7Psd<~?&Y4EXV2AHiX4K$qZ8p%;)Ke zy7!X}b??sIyXErZxCglGf%;{yZB3${nWT}$iN5_T?i`uSmmix>Y}*f1OZFePi~Y@d zR<_^b^V|k-&6cp#cv-}C71s_f_g8TG3*?Df0S$;=2Q)0v%j7ndd`QP-%6>sX5P(KP zd_=7hy@u=rwI=BXgnt)M63}m;*_slRX*v$cd18(5GL20()tcdC9?wwrXOS*lCQana zGyvEvy$1H*MS9{g>5o`cPtq|__FwW>NW-zWJDvk0t~mxyR|9{Q1_9?lBaCTsKb62| zF4u=NOs#gG1x!V>S{U{L8!lg__$ixV#Q{19KgT6MFfq;XypCu%DYx&?V3Knj`0LyTMdFHt)I(b39-LyG;WR^x z@`Ri$4ri!AG%U+H%Ui=M=ef))&_ml90k6?MFo+2athc zE^~TOW{6b0Ls=LhA%ztGpdmO742Du+w@j@C7T}}}X5|KX%V94l@V1uh{@>oiS7C(j zOTWm?;+Lp(gMgHWKbWEwP{<^53+|IIZqV>LL3V%&<(prI^y+$Ph`cS+V4f8@@$=ML z8FQEkKc(ECpmrMC2&_n9o?Ha>5RedB02>>*<-#;+n^F z9&JO=H=&+%dmbQh!zgXKCehI0u^cPsZ}ZJ3}IoWU7qz?n43z_56*#HGwrpt zIx;K@Bsf@W#z|t@YFiyyIFOrSFgEWDUIMY|+A~O;o2r~`sQ#_obH?_~%m5j{wKN0S zg?*=dDiGS%>n1Zv&A_ZbHF#;HJ@2eG1*}cHNf1O|vDJ==6GS~?o#!jJwwtJ0?2JlM zm6+2JfK&Cfm*@?#SL7AxNxSYs0+5u%;H`JUmTEA9Bsk;Q&HF0N)b^&jfBQQ^czOEx z82%phk^6ewYx@oHar=T?9|e2Wvxr)CQsxnr&SCa<+*&ZCY<~Gwyx#VdX=|>J9Zk?RML{(l+L- zi@1$mcgrJ*?azxkpYO?Ac`R^u=S=}OKT_UJyc+9)OJmb7q#I9+I*Hpob3qJ`2RVLH z#KXLSAe7no2t9ZX=YBL2+2_tH+O-)2G4H++v|D#S{*I^^ba<-x;F6&exQ&nqXMbzf z<+vfo4?E3{+#jj#Tx<&8?{a5(b)2N9iK^snq2d!9XxPnL>-LXOwBNEe2b3RWKoqx3 z2`}H}b+*?Y?+cee(3h z!DrR&&qY7k$)}6MnF+bU1AwW8Q6NU}lneXU+$*_lhVwnlO%cH15$^|_4W+2k&7RMU zhbBwKa=o3#UMQSF;VL^BcX>*RethI)GwF4@ebMCUB3m68XJaV5ILTE z62SRr6E=?rA++r{v6f~y1$)uOL+ZJ^*hZCa*i~*n;bMeVV~&Fp4;-KNG6}Art7zZ? z+WB0lmsO$VxqdCd@TSuh78lIAs!ghBaS^cMt+vir+gSEiAW^}UFYXSgt!COWTdmQF ze5+yo)`9JI`&(Yti~kC^O(bjyO8Hxi!@)bNTFllt-e_T=*(g{D<^mPX2W!E#U@gQI zT*2=;u6IFKg0(2;ErGut-V9fQx#)vnGMEo1u}+4I(R<-)xDkC8{t!rO&|3?C0NJIW z9IQktEJstpY*>-b;M`TKI;~Z!d)%gb?86@WxwnC39I#N|FKRB~!%nJuZSymx9WRq` I2!G-K0H+Z{p8x;= literal 0 HcmV?d00001 diff --git a/tippy/statistics.py b/tippy/statistics.py index 19d6584..00c2d23 100644 --- a/tippy/statistics.py +++ b/tippy/statistics.py @@ -15,15 +15,16 @@ class Histogram(): This class is designed to contain an openCV class plus some more information to ease further operations. - NOTE : Supports only 1 channel / 8 bits images for now. + NOTE : Supports only 8 bits images for now. More should be added soon. """ - def __init__(self): + def __init__(self, img, bin_fact=cv.IPL_DEPTH_8U, min_range=0): self.cvhist = None self.min_range = 0 self.depth = cv.IPL_DEPTH_8U self.nb_bins = 0 self.channels = 0 + self.compute_histogram(img, bin_fact, min_range) def compute_histogram(self, img, bin_fact=cv.IPL_DEPTH_8U, min_range=0): """ @@ -35,12 +36,12 @@ class Histogram(): max_range is automatically calculated using the input image depth. max_range = (2^img_depth) - NOTE : Supports only 1 channel / 8 bits images for now. + NOTE : Supports only 8 bits images for now. More should be added soon. """ # TESTS try: - cv.GetSize(img) + dims = cv.GetSize(img) except TypeError: raise TypeError("(%s) img : IplImage expected!" % (sys._getframe().f_code.co_name)) @@ -49,10 +50,9 @@ class Histogram(): if not(img.depth == cv.IPL_DEPTH_8U): raise TypeError("(%s) 8U image expected!" % (sys._getframe().f_code.co_name)) - elif not(img.nChannels is 1): - raise TypeError("(%s) 1C image expected!" - % (sys._getframe().f_code.co_name)) - + if img.nChannels not in [1, 3]: + raise ValueError("(%s) 1 or 3 channels image expected!" + % (sys._getframe().f_code.co_name)) # bin_fact test if (bin_fact <= 0 or ((bin_fact % 2) != 0)): raise ValueError("(%s) Positive odd integer expected!" @@ -71,43 +71,104 @@ class Histogram(): self.depth = int(img.depth) max_range = pow(2, self.depth) self.ranges = [min_range, max_range] - + + img_list = [] + # preparing images depending on nChannels + if self.channels == 1: + img_list = [img] + elif self.channels == 3: + # TODO: change this into function + img_1 = cv.CreateImage(dims, cv.IPL_DEPTH_8U, 1) + img_2 = cv.CreateImage(dims, cv.IPL_DEPTH_8U, 1) + img_3 = cv.CreateImage(dims, cv.IPL_DEPTH_8U, 1) + + cv.Split(img, img_1, img_2, img_3, None) + img_list = [img_1, img_2, img_3] + + self.cvhist = self._compute_1ch_histogram(img_list) + + def _compute_1ch_histogram(self, img_list): + """ + DESIGNED FOR INTERNAL USE ONLY. + BE CAREFUL, NO VERIFICATIONS PERFORMED + """ dims = [self.nb_bins] all_ranges = [self.ranges] - self.cvhist = cv.CreateHist( dims, - cv.CV_HIST_ARRAY, - all_ranges, - uniform=1) - cv.CalcHist([img], self.cvhist) + hist_list = [] + for img in img_list: + hist = cv.CreateHist( dims, + cv.CV_HIST_ARRAY, + all_ranges, + uniform=1) + cv.CalcHist([img], hist) + + hist_list.append(hist) + + return hist_list - def hist2table(self): + def to_tables(self): """ - Transform an histogram into a list of values. + Transforms an histogram into a list of values. This way, it is easier to process for calculations. - NOTE : Supports only 1 channel / 8 bits images for now. - More should be added soon. + Returns a list of nChannels items. + + NOTE : Supports only 8 bits images for now. + More should be added soon. """ if self.nb_bins < 1: raise TypeError("(%s) Histogram expected!" % (sys._getframe().f_code.co_name)) histable = [] - for jj in range(self.nb_bins): - histable.append(self.cvhist.bins[jj]) - + for ii in range(self.channels): + hist_list = [] + for jj in range(self.nb_bins): + hist_list.append(self.cvhist[ii].bins[jj]) + histable.append(hist_list) return histable + + def to_images(self, scale_x=3, scale_y=3, y_range=64): + """ + Creates a graphical representation of an histogram. + Outputs a list of nChannels iplimages, one for each channel of the + histogram. + The images should have the same depth as the image used to create the + histogram. + """ + if ((type(scale_x) != int) or (scale_x <= 0)): + raise TypeError("(%s) Positive integer expected!" + % (sys._getframe().f_code.co_name)) - def hist2image(self, scale_x=3, scale_y=3, y_range=64): - """ - Creates an iplimage displaying histogram results after its computation - # TODO : might be used with histable too ? - """ - if self.nb_bins < 1: - raise TypeError("(%s) Histogram expected!" + if ((type(scale_y) != int) or (scale_y <= 0)): + raise TypeError("(%s) Positive integer expected!" + % (sys._getframe().f_code.co_name)) + + if ((type(y_range) != int) or (y_range <= 0)): + raise TypeError("(%s) Positive integer expected!" % (sys._getframe().f_code.co_name)) + images = [] + for jj in range(self.channels): + images.append(self.channel_to_image(jj + 1, + scale_x, + scale_y, + y_range)) + + return images + + def channel_to_image(self, chan, scale_x=3, scale_y=3, y_range=64): + """ + Creates an iplimage displaying histogram results after its computation + """ + if ((type(chan) != int) or (chan <= 0)): + raise TypeError("(%s) Positive integer expected!" + % (sys._getframe().f_code.co_name)) + elif chan > self.channels: + raise ValueError("(%s) Incoherent channel selected!" + % (sys._getframe().f_code.co_name)) + if ((type(scale_x) != int) or (scale_x <= 0)): raise TypeError("(%s) Positive integer expected!" % (sys._getframe().f_code.co_name)) @@ -121,15 +182,15 @@ class Histogram(): % (sys._getframe().f_code.co_name)) max_range = self.ranges[1] - 1 - (_, hist_max, _, _ ) = cv.GetMinMaxHistValue(self.cvhist) + (_, hist_max, _, _ ) = cv.GetMinMaxHistValue(self.cvhist[chan - 1]) hist_img = cv.CreateImage( (max_range*scale_x, y_range*scale_y), self.depth, - self.channels) + 1) cv.Zero(hist_img) # resets image values for i in range(max_range): # 0 to max_range - hist_value = cv.QueryHistValue_1D(self.cvhist, i) - next_value = cv.QueryHistValue_1D(self.cvhist, i+1) + hist_value = cv.QueryHistValue_1D(self.cvhist[chan - 1], i) + next_value = cv.QueryHistValue_1D(self.cvhist[chan - 1], i+1) pt1 = ( int(i*scale_x), int(y_range*scale_y)) pt2 = ( int(i*scale_x+ scale_x), @@ -141,4 +202,6 @@ class Histogram(): pts = (pt1, pt2, pt3, pt4) cv.FillConvexPoly(hist_img, pts, 255, lineType=8, shift=0) - return hist_img \ No newline at end of file + return hist_img + + \ No newline at end of file diff --git a/tippy/statistics.pyc b/tippy/statistics.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3f7187e9505e159308b9ea43a851a6dcd525f2f8 GIT binary patch literal 6455 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 literal 0 HcmV?d00001 diff --git a/tippy/tests/__init__.pyc b/tippy/tests/__init__.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8d496ec5878b527d5bec5bddc39c89382a2fa02e GIT binary patch literal 136 zcmZSn%*$1G^{!ts0~9afq8yXu3FcN|YLAwqFW16Oxv?`rKHo4uC?o#+)csH*OqiYm&uYEV->%&Ds1lsZ)EQFoq;cbaqD^LL0w zD@(18)56n9;#pJJ!s}(Zx2KCZ46>2QwT&|j53^{Tm`0a|U}pX)UGtgVN8Cbx|>Gt_Z%%Nxk}T5>eL+{+vBKX^K} z3WIiG!qj~S9pBK@8xRKW!xu<#79Mpg^oB~6{!)SC;%v93{3AC%!PFwsTf z#cAKJ=N0MhDA-(SCdpU9n5ifUtCQJ&qtdP3e_!isll>*%v;sG^L&C zXnUyljeQHP*2AEEZ+#=!{%(D1GuZOiAMLc(+nctAv3R&2tcLdTE7Mx{+V}kFl+QzZ zfl~xf<<5&}Z{KeR8=LoczYT6akO|zbr++lTjnFP&g6Qb9^q{Ac!UO=P5hG>nWGmG} z)1;pQufim~CK^gaaR=H;KO35r!32*h`>|cwWx&d?tq3VZ2D7YK9vxVrlCcj)^jAWz zs#l$>&O1)stvhvR3MkqjfFiQM+#QK{@fBLrl|+jgIrb_ygkSr|Jc$p+q{W=c>MmNJ1b*>TFET3#i14xDN` zkGAu){mcJlyZ=7TJ1ypf|9RTYqex<2@}6<_--eKr_MuM3M^$0wz?nABq5?=oW(9bO z9M@^r0)%p}@#i!NLAeYB0nhg!5EBDl1aM15lM{j<%EBPPz+cdc8@z{SPUm__8^une*q@r!M6Ya literal 0 HcmV?d00001 diff --git a/tippy/tests/test_display_operations.pyc b/tippy/tests/test_display_operations.pyc new file mode 100644 index 0000000000000000000000000000000000000000..732bbb68e39eb7c00fd9d130592d3be220a4f545 GIT binary patch literal 2166 zcmcIlZEqVz5S}|bZ$}E0qN@3}2#^i|aa$o#RaNEGtxzlDNSA+(|7|PAH-|0`IbdAs7kMG z>6FfM<&E=BO{+#_*44Q_POI89+S`f`6jgSVnHhAtiR@qejC_|vI^-Z$ z1O&YB2*G~A!Y~1hhNZw|OydslK5Y;x0bY|g3y@7! zsH4()V3t!8_`(3`10L>k7M^G!L_-PbB&6SnQgI7K+@AWo$H&Fe%4cDikW9fl)61Ma zH%zWkMo;EK_UgEMpFhsD*FA6R`gnIy&uqj?BT1DHS)IJ_Tl^YUI(u5^nejJxHuy0e z?(aQLpMJmh-IH{%Kip3|;N#kVgM6*oyn&$Pe_F8v(}qeh3PGp`RL88 z?;RqHHkh82g~;?`UF_D!UdqY%AL@_TngjXNy%nqog>NAgJ6y8|G4Qx=S*!?<99`f` zPrYgWg|1PH0EUxw7MBfZlWlsVo5$5J*^oIGCT6xX4 zEu`T5Mo9m$(OGU}#N@#ESqs1nnRYi>wABc^%L{)J1P3uf8A%p?P3y{WC`5a*DwUH} z{$pNQ=FZu2mZK`Th!U8Od5~1d8JU+;7@KVPLC)7d(+@vo-NDlY0?+@4hLfc(j71&< zSn?ig$u`85LP)N$i_ducGjzluS^1Eace8SW@&^B-^I_tWTp806Ci<0xDfi2R9PWAC zc@u3Nw>h+r!{gdKX_~4zm+!Ob`7lKYi;tSLQYfXW5}fo)#;q=CQS)-Tc-QtB`_A01 zTNM>vf`EUJNB#j`k$8pq&Dod4O$4I0qnn%A*`1x4otvFW>d%G3kH7uiXo}GVkhbVqVxN#0x5d6a##5r37W)|?Q$ksyn-wjZlNLV-aVW&I{W&b&tz;nc z8v<7gwMcnJ$#NK!8{zZv^^H%;*FRfdFBCStq3MLtt@6WR&sRaYu7Y;t1@hCn*FR8^ zDQv2~=l5=vyUgG0jriAEQNjP4ehrhR9rlzqi9Hq#e1*N=C!ok4Qcgg**Z?3YXb2=N zoZSi>(8MY{X?kk(=syS;A-e1VAhtNP#VaA))XDMmcs#@7Ss{yzkQ-9sFvUx9@DJAJ znNl|#pNuW?3{q{P(F839kk1P|`^m;uy!UNR`BUM&j zvr{(Y_GG$Vq{Y%RUe)-6!OLsiLEB%VAs=4#3jlx7ffp9!*)Lc?MFN&rP0Q_0W?K`d(X^OGMS4y7fm}+wOy}x9;t@_nfU~ zyS1(Qj>!_w@3-CcrdfV%TJ2H&k&{fh(KPdz!toqSULg9x`(7)~a>I%G)J7Z_yva%L$gZ zk`EI)@rMaxC@Jl7KZROBN%aElXeat&6=hdeLoV~y|1M~C zBuG*sE|Iv@>Ec#coD>w?YZM+Q?`Y&Ey+R2DUd$25?1*A zK~K4nYSTyPwxjTcAG95$DCazZ3O$0C9(@9D`kCiQ9L4Z6~E zba~9e0^GE-vS52`fi4op-BCLjqBr8(!M{tRK2?7xK?tA?=!8A#Bar?3R2(|E@Z%l{ zMP%FrC95V$R8_3sN=c$gmn*U9WMw}PdnJ(L4I_&76DlchkE z6GrZtIE*(fM-cI7N+xQcDh=z82nc)4qQ4Y9F-GrIYsFf&J^-C6QGc>#m#p_J{+9;# zP_7$zedW6BP1o&*a!5s%>s%pm4lZElV*;@ugv8hz8sb0@ys7a;X080?e6Ersl>O+s zGHjAU7#Ie=fyME0vHjeVAMeMs;U?@@ho(6eSil}Fu6bJVmeaL@<=>7Sb_a%NXq>f* JR?%Lv{{dW}v#J09 literal 0 HcmV?d00001 diff --git a/tippy/tests/test_statistics.py b/tippy/tests/test_statistics.py index 803523f..19416f0 100644 --- a/tippy/tests/test_statistics.py +++ b/tippy/tests/test_statistics.py @@ -17,7 +17,8 @@ class Test(unittest.TestCase): This method is called before each test """ self.img_1c = cv.LoadImage("data/tippy.jpg", cv.CV_LOAD_IMAGE_GRAYSCALE) # 1 channel image - self.img_3c = cv.LoadImage("data/tippy.jpg", cv.CV_LOAD_IMAGE_COLOR) # 3 channel image + self.img_3c = cv.LoadImage("data/tippy.jpg", cv.CV_LOAD_IMAGE_COLOR) # 3 channel image + self.img_2c = cv.CreateImage((10, 10), cv.IPL_DEPTH_8U, 2) # fake 2 channels image self.img_16s = cv.CreateImage((15, 15), cv.IPL_DEPTH_16S, 1) # Non 8 bits image self.val = 10 # non Image @@ -33,48 +34,77 @@ class Test(unittest.TestCase): #--- ## TESTS def test_compute_histogram(self): - hist = st.Histogram() # testing input image - self.assertRaises(TypeError, lambda:hist.compute_histogram(self.val) ) - self.assertRaises(TypeError, lambda:hist.compute_histogram(self.img_3c)) - + self.assertRaises(TypeError, lambda:st.Histogram(self.val) ) + self.assertRaises(TypeError, lambda:st.Histogram(self.img_16s) ) + self.assertRaises(ValueError, lambda:st.Histogram(self.img_2c) ) # testing bin_fact self.assertRaises(ValueError, - lambda: hist.compute_histogram(self.img_1c, self.neg_val)) + lambda: st.Histogram(self.img_1c, self.neg_val)) self.assertRaises(TypeError, - lambda: hist.compute_histogram(self.img_1c, self.string)) + lambda: st.Histogram(self.img_1c, self.string)) # testing min_range. It can be either negative or even. self.assertRaises(TypeError, - lambda: hist.compute_histogram(self.img_1c, self.val, self.string)) + lambda: st.Histogram(self.img_1c, self.val, self.string)) - def test_hist2table(self): - hist = st.Histogram() - # testing input histogram - self.assertRaises(TypeError, lambda: hist.hist2table(self.val)) + # testing output + hist_1c = st.Histogram(self.img_1c) + self.assertEquals(self.img_1c.nChannels, hist_1c.channels) + hist_3c = st.Histogram(self.img_3c) + self.assertEquals(self.img_3c.nChannels, hist_3c.channels) + + def test_to_tables(self): # testing output size - hist.compute_histogram(self.img_1c) - histable = hist.hist2table() - self.assertEqual(256, len(histable)) + hist = st.Histogram(self.img_3c) + histable = hist.to_tables() + self.assertEqual(3, len(histable)) + self.assertEqual(256, len(histable[0])) - def test_hist2image(self): - hist = st.Histogram() - # testing input histogram - self.assertRaises(TypeError, lambda: hist.hist2image(self.val)) + def test_channel_to_image(self): + hist = st.Histogram(self.img_3c) + # testing channel value + self.assertRaises(ValueError, + lambda: hist.channel_to_image(4)) + self.assertRaises(TypeError, + lambda: hist.channel_to_image(self.string)) + self.assertRaises(TypeError, + lambda: hist.channel_to_image(self.neg_val)) # testing scale inputs self.assertRaises(TypeError, - lambda: hist.hist2image(hist, self.string)) + lambda: hist.channel_to_image(1, self.string)) self.assertRaises(TypeError, - lambda: hist.hist2image(hist, self.neg_val)) + lambda: hist.channel_to_image(1, self.neg_val)) self.assertRaises(TypeError, - lambda: hist.hist2image(hist, self.val, self.string)) + lambda: hist.channel_to_image(1, self.val, self.string)) self.assertRaises(TypeError, - lambda: hist.hist2image(hist, self.val, self.neg_val)) + lambda: hist.channel_to_image(1, self.val, self.neg_val)) # testing range inputs self.assertRaises(TypeError, - lambda: hist.hist2image(hist, self.val, self.val, self.string)) + lambda: hist.channel_to_image(1, self.val, self.val, self.string)) self.assertRaises(TypeError, - lambda: hist.hist2image(hist, self.val, self.val, self.neg_val)) + lambda: hist.channel_to_image(1, self.val, self.val, self.neg_val)) + + def test_to_images(self): + hist = st.Histogram(self.img_3c) + # testing scale inputs + self.assertRaises(TypeError, + lambda: hist.to_images(self.string)) + self.assertRaises(TypeError, + lambda: hist.to_images(self.neg_val)) + self.assertRaises(TypeError, + lambda: hist.to_images(self.val, self.string)) + self.assertRaises(TypeError, + lambda: hist.to_images(self.val, self.neg_val)) + # testing range inputs + self.assertRaises(TypeError, + lambda: hist.to_images(self.val, self.val, self.string)) + self.assertRaises(TypeError, + lambda: hist.to_images(self.val, self.val, self.neg_val)) + + # testing outputs + self.assertEqual(hist.channels, len(hist.to_images())) + #if __name__ == "__main__": #import sys;sys.argv = ['', 'Test.testName'] #unittest.main() \ No newline at end of file diff --git a/tippy/tests/test_statistics.pyc b/tippy/tests/test_statistics.pyc new file mode 100644 index 0000000000000000000000000000000000000000..844aa0124e4ecf957e38869bfa281a4cec3014b0 GIT binary patch literal 6896 zcmc&(|8EpU6rbI@Uhj@puoWy~^du;kDAYoNNC;`YRslR2Yrn6As`Ja??>vgW z4H7A}0qUs8Rdq*gpknK;+Hkw|oZ8K+jWHGFRP3nTg4)8Ey!uJ0CrUlo80X}*>KNC& z4^pnR$w-s}`_C$OT#QC^Z!QGl)@YSFmBlRZm>?qf&nEV1K^bKPLTH zyCf9=lv7V~GNssMm8DYR{vB4CVshDIDk?~2LPg_JnN(2`5FevBS3$~^&ToAu(UnFF zRHF)NVNkCF_|15$)s8E15bjhA!0HXxuVHc&m|)f>0SQcLHQsM=D}169?_Z)(_3MQP(s8m6wwcVjh5h z^&cS5aAPpsQBRdP4oCe0$KficpW*f~-0qCr^BDO)MsJU?=P?Rh2224?jUwRwIqI<^ z^+Km-7uOD+t|)S*LrXH$%?vFm4t2XjBL%I|;8J%>XlUb_3b1a3yTXT1!&J>ml~~Co z(nc=PO;}G0p0VN4oU15GMy5(Unn@P1;PpCuZWP@30CmkBLK6P|tHd6U<-I||8##0_ zy^~n=Jj#*96UT*xhKizy$3q_!kGdo<`V>f3-_M|RgaL+1t99Oz42JX*9^L6^fcy|E z4^vX{{#bMPm|hr=lt>AtbT)&S5?RFFTn|}+k`t_TN|QIq8=cT|SYF_*(%1|yM4&Zt z8ZSsRLIY#t`lG#gsoicN(Lw8eP~W%BJ|oCXUiyANsN2cS+D_1H#%L8WIqWn%IvepH z;u|EeAtf-3tYk_3a@c25NAn(H*f^3Owir0 z;fNQe&8#HcDPcO7prRzf%b-n!L^G!4n_#n!LowH|iWBT5V?fN$K+J`CV$lODoM-_C z$L41*oh(Q?MQnQ#eabbda^+4r6V9nLU!Wj7pFWQBb#4Vv6M%k2+!X|o&OGgpyOuFV z##2XaAC#EgN0 z@w=!Tg0Zz;Af5j|kzOB_+#|-D-=gH|9TxUIW-;Cj2|rYb?@zs_^$%ysWjr`qzQkt? zzYh5QVP&36^ZliqsZOdijdW=mb@|JBrXBLxz{0D^%cg$=d2!(H#P{^gZDX+{1<#57 zSzdqa&+__Xf0oxD`?I_Qv42d=zMzn-(*E(_#NR=_GjTQ3uLz zs0x(S#na)*y{7TJKu+&G_?b7~NF3$2*yEshy$HlRkQJ}v*V8AexO5TnRk-x;h9~KW zUCZWxq`h#-Cu%>YJwKj4QC}^x@v!9`F}~Yfd8>Rk_r2Jx>!#QCDkNt}-Xo!@P0EfJh4aDByS`89|!3t oZaGTY6kW;Gbxf-TI+iVmc?Mbiy2b8B0dmRnxPZs;gnQim2NTXT