├── docde ├── 1.mat ├── 2.mat ├── 3.mat ├── 4.mat ├── 124084.jpg ├── sqdist.m ├── JCalculation.m ├── class2Img.m ├── heap_add.m ├── QuantizedC.m ├── build_heap.m ├── DrawLine.m ├── JAverage.m ├── SpatialSeg.m ├── GenerateWindow.m ├── LiuYang.m ├── Borsotti.m ├── Fratio.m ├── heap_pop.m ├── EVisible.m ├── JImage.m ├── ValleyD.m ├── SeedGrowing.m ├── RegionMerge.m ├── RegionMerge_RGB.m ├── script.m ├── ValleyG2.m ├── ssim_index.m ├── ValleyG1.m ├── Evaluation.m ├── kmeansO.m ├── SegEval.m ├── PNN_fast.m └── PNN_fast_RGBo.m ├── Inputs └── 124084.jpg ├── Outputs └── result.jpg ├── calcSval.m ├── findStatistic.m ├── findNeighbour.m ├── DrawLine.m ├── README.md ├── RegionGrowing.m ├── Demo.m ├── RegionMerging.m └── LICENSE /docde/1.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/balcilar/Color-Image-Segmentation-Using-Region-Growing-and-Region-Merging/HEAD/docde/1.mat -------------------------------------------------------------------------------- /docde/2.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/balcilar/Color-Image-Segmentation-Using-Region-Growing-and-Region-Merging/HEAD/docde/2.mat -------------------------------------------------------------------------------- /docde/3.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/balcilar/Color-Image-Segmentation-Using-Region-Growing-and-Region-Merging/HEAD/docde/3.mat -------------------------------------------------------------------------------- /docde/4.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/balcilar/Color-Image-Segmentation-Using-Region-Growing-and-Region-Merging/HEAD/docde/4.mat -------------------------------------------------------------------------------- /Inputs/124084.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/balcilar/Color-Image-Segmentation-Using-Region-Growing-and-Region-Merging/HEAD/Inputs/124084.jpg -------------------------------------------------------------------------------- /docde/124084.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/balcilar/Color-Image-Segmentation-Using-Region-Growing-and-Region-Merging/HEAD/docde/124084.jpg -------------------------------------------------------------------------------- /Outputs/result.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/balcilar/Color-Image-Segmentation-Using-Region-Growing-and-Region-Merging/HEAD/Outputs/result.jpg -------------------------------------------------------------------------------- /docde/sqdist.m: -------------------------------------------------------------------------------- 1 | function d = sqdist(a,b) 2 | % sqdist - computes pairwise squared Euclidean distances between points 3 | 4 | % original version by Roland Bunschoten, 1999 5 | 6 | if size(a,1)==1 7 | d = repmat(a',1,length(b)) - repmat(b,length(a),1); 8 | d = d.^2; 9 | else 10 | aa = sum(a.*a); bb = sum(b.*b); ab = a'*b; 11 | d = abs(repmat(aa',[1 size(bb,2)]) + repmat(bb,[size(aa,2) 1]) - 2*ab); 12 | end 13 | -------------------------------------------------------------------------------- /calcSval.m: -------------------------------------------------------------------------------- 1 | function Sval=calcSval(Stat,Con) 2 | 3 | %% Written by Muhammet Balcilar, France 4 | % all rights reverved 5 | 6 | 7 | Sval=zeros(size(Con,1),1); 8 | 9 | for itr=1:size(Con,1) 10 | muA =Stat{Con(itr,1)}.mean'; 11 | muB =Stat{Con(itr,2)}.mean'; 12 | covA=Stat{Con(itr,1)}.cov; 13 | covB=Stat{Con(itr,2)}.cov; 14 | 15 | Sval(itr)=(muA-muB)'*inv(covA+covB)*(muA-muB); 16 | end 17 | 18 | -------------------------------------------------------------------------------- /findStatistic.m: -------------------------------------------------------------------------------- 1 | function Stat=findStatistic(Region,image) 2 | %% Written by Muhammet Balcilar, France 3 | % all rights reverved 4 | n=length(unique(Region(:))); 5 | 6 | R=image(:,:,1); 7 | G=image(:,:,2); 8 | B=image(:,:,3); 9 | 10 | R=double(R(:)); 11 | G=double(G(:)); 12 | B=double(B(:)); 13 | 14 | region=Region(:); 15 | 16 | for i=1:n 17 | I=find(region==i); 18 | tmp=[R(I) G(I) B(I)]; 19 | Stat{i}.mean=mean(tmp); 20 | Stat{i}.cov=cov(tmp); 21 | end 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /docde/JCalculation.m: -------------------------------------------------------------------------------- 1 | function J = JCalculation(class_map, M, St); 2 | 3 | 4 | [m, n] = size(class_map); 5 | N = m*n; 6 | Sw = 0; 7 | 8 | for l = 1: max(class_map(:)), 9 | [x,y] = find(class_map == l); 10 | % mean vector of the vectors with class label l 11 | if isempty(x) 12 | continue; 13 | end 14 | m_l = [mean(x), mean(y)]; 15 | % m_l = [median(x), median(y)]; 16 | m1 = repmat(m_l, length(x), 1); 17 | xy = [x, y]; 18 | Dist1 = sum(diag(sqdist(xy', m1'))); 19 | Sw = Sw + Dist1; 20 | end 21 | 22 | J = (St-Sw)/Sw; 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /docde/class2Img.m: -------------------------------------------------------------------------------- 1 | function Img = class2Img(class_map, OrI) 2 | % input: class_map -- the segment label for each pixel 3 | % OrI -- original image 4 | % output: Img -- segmented image (quantized/average) 5 | 6 | [m, n, d] = size(OrI); 7 | 8 | Img = zeros(m,n,d); 9 | for i = 1:max(class_map(:)), 10 | sq = find(class_map == i); 11 | Channel = zeros(m,n); 12 | for j = 1:d, 13 | Channel = OrI(:,:, j); 14 | u = mean(Channel(sq)); 15 | Channel = zeros(m,n); 16 | Channel(sq) = u; 17 | Img(:,:, j) = Img(:,:,j) + Channel; 18 | end 19 | end 20 | 21 | -------------------------------------------------------------------------------- /docde/heap_add.m: -------------------------------------------------------------------------------- 1 | function [hp,hpind] = heap_add(hp,hpind,addval,addind) 2 | %invind is current pos of 1:l point in hps 3 | l = length(hp)+1; 4 | hp(l) = addval; 5 | hpind(l) = addind; 6 | curnode = l; 7 | while (curnode>1) 8 | parnode = fix(curnode/2); 9 | if hp(parnode)>hp(curnode)%FOR MIN-heaps 10 | %swap value 11 | tmp = hp(parnode); 12 | hp(parnode) = hp(curnode); 13 | hp(curnode) = tmp; 14 | %swap heapind 15 | tmp = hpind(parnode); 16 | hpind(parnode) = hpind(curnode); 17 | hpind(curnode) = tmp; 18 | curnode = parnode; 19 | else 20 | break; 21 | end 22 | end -------------------------------------------------------------------------------- /findNeighbour.m: -------------------------------------------------------------------------------- 1 | function [N Con]=findNeighbour(Region,mnadj) 2 | 3 | %% Written by Muhammet Balcilar, France 4 | % all rights reverved 5 | 6 | n=length(unique(Region(:))); 7 | N=zeros(n,n); 8 | Con=[]; 9 | 10 | for i=1:size(Region,1)-1 11 | for j=1:size(Region,2)-1 12 | tmp=Region(i:i+1,j:j+1); 13 | I=unique(tmp(:)); 14 | if length(I)>1 15 | 16 | if N(I(1),I(2))==mnadj-1 17 | Con=[Con;min(I(1),I(2)) max(I(1),I(2)) ]; 18 | end 19 | N(I(1),I(2))=N(I(1),I(2))+1; 20 | N(I(2),I(1))=N(I(2),I(1))+1; 21 | end 22 | end 23 | end 24 | 25 | -------------------------------------------------------------------------------- /docde/QuantizedC.m: -------------------------------------------------------------------------------- 1 | function qc = QuantizedC(class_map, OrI) 2 | % input: class_map -- the segment label for each pixel 3 | % OrI -- original image 4 | % output: Img -- segmented image (quantized/average) 5 | % qc -- quantized color 6 | 7 | [m, n, d] = size(OrI); 8 | k = max(class_map); 9 | qc = zeros(k, d); 10 | 11 | for i = 1:max(class_map(:)), 12 | sq = find(class_map == i); 13 | Channel = zeros(m,n); 14 | for j = 1:d, 15 | Channel = OrI(:,:, j); 16 | u = mean(Channel(sq)); 17 | Channel = zeros(m,n); 18 | Channel(sq) = u; 19 | qc(i,j) = u; 20 | end 21 | end 22 | 23 | -------------------------------------------------------------------------------- /docde/build_heap.m: -------------------------------------------------------------------------------- 1 | function [hp, hpind] = build_heap(x,sq) 2 | l = length(x); 3 | hp = x; 4 | hpind = sq; 5 | 6 | 7 | for i = 2:l 8 | curnode = i; 9 | while (curnode>1) 10 | parnode = fix(curnode/2); 11 | if hp(parnode)>hp(curnode)%FOR MIN-hp 12 | %swap value 13 | tmp = hp(parnode); 14 | hp(parnode) = hp(curnode); 15 | hp(curnode) = tmp; 16 | %swap hpind 17 | tmp = hpind(parnode); 18 | hpind(parnode) = hpind(curnode); 19 | hpind(curnode) = tmp; 20 | curnode = parnode; 21 | else 22 | break; 23 | end 24 | end 25 | end 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /DrawLine.m: -------------------------------------------------------------------------------- 1 | function DrawLine(SegI) 2 | % input: SegI --- Segments with segment labels 3 | % output: ImgS --- Segments with line boundaries 4 | 5 | [m, n] = size(SegI); 6 | ImgS = zeros(m, n); 7 | % RGB = label2rgb(SegI); 8 | % figure; imshow(RGB); 9 | % hold on; 10 | BRegion = imdilate(SegI, [0 1 0; 1 1 1; 0 1 0]); 11 | Boundary = BRegion & ~SegI; 12 | 13 | 14 | for i = 1:max(SegI(:)), 15 | S = zeros(m, n); 16 | [x, y] = find(SegI == i); 17 | for j = 1:length(x), 18 | S(x(j), y(j)) = 1; 19 | end 20 | [B,L] = bwboundaries(S,'noholes'); 21 | for k = 1:length(B) 22 | boundary = B{k}; 23 | plot(boundary(:,2), boundary(:,1), 'w', 'LineWidth', 1); 24 | end 25 | ImgS = ImgS + S; 26 | end 27 | 28 | -------------------------------------------------------------------------------- /docde/DrawLine.m: -------------------------------------------------------------------------------- 1 | function DrawLine(SegI) 2 | % input: SegI --- Segments with segment labels 3 | % output: ImgS --- Segments with line boundaries 4 | 5 | [m, n] = size(SegI); 6 | ImgS = zeros(m, n); 7 | % RGB = label2rgb(SegI); 8 | % figure; imshow(RGB); 9 | % hold on; 10 | BRegion = imdilate(SegI, [0 1 0; 1 1 1; 0 1 0]); 11 | Boundary = BRegion & ~SegI; 12 | 13 | 14 | for i = 1:max(SegI(:)), 15 | S = zeros(m, n); 16 | [x, y] = find(SegI == i); 17 | for j = 1:length(x), 18 | S(x(j), y(j)) = 1; 19 | end 20 | [B,L] = bwboundaries(S,'noholes'); 21 | for k = 1:length(B) 22 | boundary = B{k}; 23 | plot(boundary(:,2), boundary(:,1), 'w', 'LineWidth', 1); 24 | end 25 | ImgS = ImgS + S; 26 | end 27 | 28 | -------------------------------------------------------------------------------- /docde/JAverage.m: -------------------------------------------------------------------------------- 1 | function JA = JAverage(class_map, Region); 2 | 3 | 4 | [m, n] = size(Region); 5 | N = m*n; 6 | JA = 0; 7 | for l = 1: max(Region(:)), 8 | % calculate J value for each region 9 | TRegion = zeros(m, n); 10 | [x,y] = find(Region == l); 11 | xxx = find(Region == l); 12 | if isempty(x) 13 | continue; 14 | end 15 | TRegion(xxx) = class_map(xxx); 16 | St = 0; 17 | % mean vector of the vectors with class label l 18 | z = [x y]; 19 | M = mean(z); 20 | for i = 1:length(z), 21 | m2 = repmat(M, length(z), 1); 22 | St = sum(diag(sqdist(z', m2'))); 23 | end 24 | J = JCalculation(TRegion, M, St); 25 | JA = JA + J*length(z); 26 | end 27 | JA = JA/max(Region(:)); 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /docde/SpatialSeg.m: -------------------------------------------------------------------------------- 1 | function ImgSeg = SpatialSeg(JI, RS, wi) 2 | 3 | [m, n] = size(JI); 4 | ImgSeg = zeros(m,n); 5 | Sno = 0; 6 | % figure; 7 | for r = 1:max(RS(:)), 8 | % one region to multiple 9 | Region = zeros(m,n); 10 | Region(:, :) = NaN; 11 | temp = []; 12 | xy = find(RS == r); 13 | Region(xy) = JI(xy); 14 | temp = [temp JI(xy)]; 15 | u = sum(temp)/length(xy); 16 | s = std(temp); 17 | 18 | Region = ValleyD(Region, wi, u, s); 19 | sq = find(Region ~=0); 20 | Region(sq) = Region(sq) + Sno; 21 | ImgSeg = ImgSeg + Region; 22 | Sno = max(ImgSeg(:)); 23 | % % fprintf('%d\n', Sno); 24 | % % imshow(ImgSeg); 25 | % % hold on; 26 | % % pause(2) 27 | end 28 | 29 | ImgSeg = ValleyG1(JI, ImgSeg); 30 | 31 | 32 | -------------------------------------------------------------------------------- /docde/GenerateWindow.m: -------------------------------------------------------------------------------- 1 | function W = GenerateWindow(scale); 2 | 3 | window = ones(65, 65); 4 | % left up block of the window 5 | lu = ones(32,32); 6 | % left bottom 7 | lb = ones(32,32); 8 | % right up 9 | ru = ones(32,32); 10 | % right bottom 11 | rb = ones(32,32); 12 | 13 | % left up 14 | j = 1; 15 | for i = 24:-2:10, 16 | lu(j,1:i) = 0; 17 | lu(1:i,j) = 0; 18 | j = j + 1; 19 | end 20 | 21 | % 90 degree counterclockwise rotation of matrix 22 | lb = rot90(lu); 23 | rb = rot90(lb); 24 | ru = rot90(rb); 25 | window(1:32, 1:32) = lu; 26 | window(1:32, 34:65) = ru; 27 | window(34:65, 1:32) = lb; 28 | window(34:65, 34:65) = rb; 29 | 30 | w4 = window; 31 | w3 = w4(1:2:end, 1:2:end); 32 | w2 = w3(1:2:end, 1:2:end); 33 | w1 = w2(1:2:end, 1:2:end); 34 | 35 | if scale == 4, 36 | W = w4; 37 | elseif scale == 3, 38 | W = w3; 39 | elseif scale == 2, 40 | W = w2; 41 | else scale == 1, 42 | W = w1; 43 | end 44 | -------------------------------------------------------------------------------- /docde/LiuYang.m: -------------------------------------------------------------------------------- 1 | 2 | 3 | function Score = LiuYang(Im, CMap) 4 | 5 | % image property 6 | [Ih, Iw, d] = size(Im); 7 | % segmentation no. 8 | Rn = max(CMap(:)); 9 | 10 | % within cluster 11 | Rmean = zeros(Rn, d); 12 | color_err = zeros(1, Rn); 13 | % for each region 14 | for i = 1:Rn, 15 | sqerr = 0; 16 | sq = find(CMap == i); 17 | Si = length(sq); 18 | for dim = 1:d, 19 | Ri = zeros(Ih, Iw); 20 | Aver_id = zeros(Ih, Iw); 21 | temp1 = Im(:,:,dim); 22 | Ri(sq) = temp1(sq); 23 | % Aver_id -- average value 24 | Aver_id(sq) = sum(Ri(:))/Si; 25 | Rmean(i,dim) = sum(Ri(:))/Si; 26 | % squared color error 27 | sqerr = sqerr + sum(sum((Ri - Aver_id).^2)); 28 | end 29 | color_err(i) = sqerr / sqrt(Si); 30 | end 31 | within_err = sum(color_err)/(sqrt(Rn)); 32 | 33 | % % between cluster 34 | % between_err = sum(pdist(Rmean, 'euclidean')); 35 | 36 | Score = within_err; 37 | 38 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Unsupervised color image segmentation using Region Growing and Region Merging 2 | 3 | This project is reimplementation of research on color image segmentataion using region growing and region merging respectively [1]. We prepared a demo code that you can load flower image and see 4 different level of region growing results from coarsed one to refined one. After you can see how the region merging has an effect on refined version of region growing. Here is the original input, all 4 level of region growing results and also final segmentation result. In this demo we feed region merging function with scale1 region growing results. But note you can feed the region merging function with either sclae 2, scale 3 or scale 4. 4 | 5 | ![Sample image](Outputs/result.jpg?raw=true "Title") 6 | 7 | To run provided demo, please run Demo script as follows; 8 | 9 | ``` 10 | > Demo 11 | ``` 12 | 13 | ## Reference 14 | [1] Balasubramanian, Guru Prashanth, et al. "Unsupervised color image segmentation using a dynamic color gradient thresholding algorithm." Human Vision and Electronic Imaging XIII. Vol. 6806. International Society for Optics and Photonics, 2008. 15 | -------------------------------------------------------------------------------- /docde/Borsotti.m: -------------------------------------------------------------------------------- 1 | 2 | 3 | function Score = Borsotti(Im, CMap) 4 | % image property 5 | [Ih, Iw, d] = size(Im); 6 | SI = Ih*Iw; 7 | % segmentation no. 8 | Rn = max(CMap(:)); 9 | 10 | % within cluster 11 | Rmean = zeros(Rn, d); 12 | color_err = zeros(1, Rn); 13 | Area = zeros(1, Rn); 14 | for j = 1:Rn, 15 | Area(j) = length(find(CMap == j)); 16 | end 17 | % N(x) -- the number of regions have area x (stupid way to calculate) 18 | for x = 1:Rn, 19 | Nx(x) = length(find(Area == Area(x))); 20 | end 21 | 22 | % for each region 23 | for i = 1:Rn, 24 | sqerr = 0; 25 | sq = find(CMap == i); 26 | Si = Area(i); 27 | 28 | for dim = 1:d, 29 | Ri = zeros(Ih, Iw); 30 | Aver_id = zeros(Ih, Iw); 31 | temp1 = Im(:,:,dim); 32 | Ri(sq) = temp1(sq); 33 | % Aver_id -- average value 34 | Aver_id(sq) = sum(Ri(:))/Si; 35 | Rmean(i,dim) = sum(Ri(:))/Si; 36 | % squared color error 37 | sqerr = sqerr + sum(sum((Ri - Aver_id).^2)); 38 | end 39 | color_err(i) = sqerr / (1+log(Si)) + (Nx(i)/Si)^2; 40 | end 41 | within_err = 1/(1000*SI)*sqrt(Rn)*sum(color_err); 42 | 43 | Score = within_err; 44 | 45 | -------------------------------------------------------------------------------- /docde/Fratio.m: -------------------------------------------------------------------------------- 1 | 2 | 3 | function [Einter, Eintra, Score] = Fratio(Im, CMap) 4 | 5 | % image property 6 | [Ih, Iw, d] = size(Im); 7 | % segmentation no. 8 | Rn = max(CMap(:)); 9 | % image average 10 | for dd = 1:d, 11 | Channel = Im(:,:,dd); 12 | Imean(1,dd) = mean(Channel(:)); 13 | end 14 | 15 | % segmented image with average color of that region 16 | Seg = zeros(Ih, Iw, d); 17 | Einter = 0; 18 | % for each region 19 | for i = 1:Rn, 20 | sq = find(CMap == i); 21 | Si = length(sq); 22 | for dim = 1:d, 23 | Aver_id = zeros(Ih, Iw); 24 | Ri = zeros(Ih, Iw); 25 | temp1 = Im(:,:,dim); 26 | Ri(sq) = temp1(sq); 27 | Aver_id(sq) = sum(Ri(:))/Si; 28 | Rmean(1,dim) = sum(Ri(:))/Si; 29 | Ri(sq) = Aver_id(sq); 30 | Seg(:,:,dim) = Seg(:,:,dim) + Ri; 31 | end 32 | dist = sum((Rmean-Imean).^2) *Si; 33 | Einter = Einter + dist; 34 | end 35 | Einter = Einter/(Ih*Iw); 36 | 37 | % intra-region error 38 | Diff = zeros(Ih, Iw, d); 39 | Diff = double(Im) - Seg; 40 | Diff = Diff(:,:,1).^2 + Diff(:,:,2).^2 + Diff(:,:,3).^2; 41 | 42 | Eintra = sum(Diff(:))/(Ih*Iw); 43 | 44 | Score = Rn*Eintra/Einter; 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /RegionGrowing.m: -------------------------------------------------------------------------------- 1 | function [Region1 Region2 Region3 Region4]=RegionGrowing(image_org) 2 | 3 | %% Written by Muhammet Balcilar, France 4 | % all rights reverved 5 | 6 | 7 | [m,n,d] = size(image_org); 8 | 9 | 10 | X = reshape(double(image_org), m*n,d); 11 | [tmp,M,tmp2,P] = kmeansO(X,[],16,0,0,0,0); 12 | map = reshape(P, m, n); 13 | 14 | for w = 1:4 15 | W = GenerateWindow(w); 16 | JI{w} = JImage(map, W); 17 | end 18 | 19 | 20 | ImgQ = class2Img(map, image_org); 21 | Region = zeros(m, n); 22 | 23 | u = mean(JI{4}(:)); 24 | s = std(JI{4}(:)); 25 | Region = ValleyD(JI{4}, 4, u, s); 26 | Region = ValleyG1(JI{4}, Region); 27 | Region = ValleyG1(JI{3}, Region); 28 | Region = ValleyG2(JI{1}, Region); 29 | Region4 = Region; 30 | 31 | 32 | w = 3; 33 | Region = SpatialSeg(JI{3}, Region, w); 34 | Region = ValleyG1(JI{2}, Region); 35 | Region = ValleyG2(JI{1}, Region); 36 | Region3 = Region; 37 | 38 | w = 2; 39 | Region = SpatialSeg(JI{2}, Region, w); 40 | Region = ValleyG1(JI{1}, Region); 41 | Region = ValleyG2(JI{1}, Region); 42 | Region2 = Region; 43 | 44 | w = 1; 45 | Region = SpatialSeg(JI{1}, Region, w); 46 | Region = ValleyG2(JI{1}, Region); 47 | Region1 = Region; 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /Demo.m: -------------------------------------------------------------------------------- 1 | %% Written by Muhammet Balcilar, France 2 | % all rights reverved 3 | 4 | clear all 5 | clc 6 | addpath('docde') 7 | 8 | 9 | filename = 'Inputs/124084.jpg'; 10 | image = imread(filename); 11 | 12 | %% Region Growing method 13 | [Region1 Region2 Region3 Region4]=RegionGrowing(image); 14 | 15 | figure; imshow(uint8(image)); 16 | hold on; 17 | DrawLine(Region1); 18 | hold off; 19 | title('Scale 1'); 20 | 21 | figure; imshow(uint8(image)); 22 | hold on; 23 | DrawLine(Region2); 24 | hold off; 25 | title('Scale 2'); 26 | 27 | figure; imshow(uint8(image)); 28 | hold on; 29 | DrawLine(Region3); 30 | hold off; 31 | title('Scale 3'); 32 | 33 | figure; imshow(uint8(image)); 34 | hold on; 35 | DrawLine(Region4); 36 | hold off; 37 | title('Scale 4'); 38 | 39 | 40 | %% Region merging method 41 | % method has two parameters minimum adjacent pixel which means connected 42 | % regions has at least this number of pixel connected 43 | mnadj=10; 44 | % threshold value to make decision to merge two region or nor 45 | RMThresh=3.5; 46 | 47 | RegionResult=RegionMerging(image,Region1,mnadj,RMThresh); 48 | 49 | % figure results 50 | figure; imshow(uint8(image)); 51 | hold on; 52 | DrawLine(RegionResult); 53 | hold off; 54 | title('Final segmentation'); 55 | -------------------------------------------------------------------------------- /docde/heap_pop.m: -------------------------------------------------------------------------------- 1 | function [hp,hpind,minval,minind] = heap_pop(hp,hpind) 2 | %pop min value in heap 3 | if length(hp)==0 4 | disp('empty heap, no pop operation') 5 | return; 6 | end 7 | l = length(hp); 8 | minval = hp(1); 9 | minind = hpind(1); 10 | hp(1) = hp(l); 11 | hpind(1) = hpind(l); 12 | l = l-1; 13 | hp = hp(1:l); 14 | hpind = hpind(1:l); 15 | 16 | 17 | curnode = 1; 18 | halfl = fix(l/2); 19 | while (curnode<=halfl) 20 | sonnode1 = curnode*2; 21 | sonnode2 = sonnode1 +1; 22 | val1 = hp(curnode); 23 | val2 = hp(sonnode1); 24 | if l>=sonnode2 25 | val3 = hp(sonnode2); 26 | else 27 | val3 = inf; 28 | end 29 | if val1>val2 30 | if val2>val3 31 | %1>2>3,move3 32 | stat=3; 33 | else 34 | %1>2,3>2, move 2 35 | stat =2; 36 | end 37 | else 38 | if val1>val3 39 | %2>1>3 move 3 40 | stat = 3; 41 | else 42 | %2>1,3>1, stop 43 | stat = 0; 44 | end 45 | end 46 | if (stat==0) 47 | break; 48 | elseif (stat==3) 49 | %swap value,1<->3 50 | hp(sonnode2) = val1; 51 | hp(curnode) = val3; 52 | %swap heapind 53 | tmp = hpind(curnode); 54 | hpind(curnode) = hpind(sonnode2); 55 | hpind(sonnode2) = tmp; 56 | curnode = sonnode2; 57 | else % stat==2 58 | %swap value,1<->2 59 | hp(sonnode1) = val1; 60 | hp(curnode) = val2; 61 | %swap heapind 62 | tmp = hpind(curnode); 63 | hpind(curnode) = hpind(sonnode1); 64 | hpind(sonnode1) = tmp; 65 | curnode = sonnode1; 66 | end 67 | end 68 | 69 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /docde/EVisible.m: -------------------------------------------------------------------------------- 1 | 2 | 3 | function [Eintra, Einter] = EVisible(Im, CMap, th) 4 | 5 | % image property 6 | [Ih, Iw, d] = size(Im); 7 | % segmentation no. 8 | Rn = max(CMap(:)); 9 | 10 | % segmented image with average color of that region 11 | Seg = zeros(Ih, Iw, d); 12 | Rmean = zeros(Rn, d); 13 | % for each region 14 | for i = 1:Rn, 15 | sq = find(CMap == i); 16 | Si = length(sq); 17 | for dim = 1:d, 18 | Aver_id = zeros(Ih, Iw); 19 | Ri = zeros(Ih, Iw); 20 | temp1 = Im(:,:,dim); 21 | Ri(sq) = temp1(sq); 22 | Aver_id(sq) = sum(Ri(:))/Si; 23 | Rmean(i,dim) = sum(Ri(:))/Si; 24 | Ri(sq) = Aver_id(sq); 25 | Seg(:,:,dim) = Seg(:,:,dim) + Ri; 26 | end 27 | end 28 | 29 | % intra-region error 30 | Diff = zeros(Ih, Iw, d); 31 | Diff = double(Im) - Seg; 32 | Diff = sqrt(Diff(:,:,1).^2 + Diff(:,:,2).^2 + Diff(:,:,3).^2); 33 | th1 = repmat(th, Ih, Iw); 34 | Eintra = length(find((Diff-th1)>0))/(Ih*Iw); 35 | 36 | % inter-region error 37 | E_diff = zeros(1, Rn*(Rn-1)/2); 38 | E_diff(th-sqrt(pdist(Rmean))>0) = 1; 39 | wts = []; 40 | for t = 1:Rn, 41 | for s = t+1:Rn, 42 | R1 = zeros(Ih, Iw); 43 | sq1 = find(CMap == t); 44 | R1(sq1) = t; 45 | BRegion1 = imdilate(R1, [0 1 0; 1 1 1; 0 1 0]); 46 | Boundary1 = BRegion1 & ~R1; 47 | R2 = zeros(Ih, Iw); 48 | sq2 = find(CMap == s); 49 | R2(sq2) = s; 50 | BRegion2 = imdilate(R2, [0 1 0; 1 1 1; 0 1 0]); 51 | Boundary2 = BRegion2 & ~R2; 52 | R = R1 + R2; 53 | BRegion = imdilate(R, [0 1 0; 1 1 1; 0 1 0]); 54 | Boundary = BRegion & ~R; 55 | Bw = Boundary1+Boundary2-Boundary; 56 | Bw = bwmorph(Bw, 'thin'); 57 | wts = [wts length(find(Bw))]; 58 | end 59 | end 60 | 61 | C = 1/6; 62 | Einter = sum(wts.*E_diff)/(C*Ih*Iw); 63 | 64 | 65 | -------------------------------------------------------------------------------- /docde/JImage.m: -------------------------------------------------------------------------------- 1 | function JI = JImage(I, W); 2 | 3 | [m, n] = size(I); 4 | % window size 5 | ws = size(W, 1); 6 | if ws == 9, 7 | d = 1; 8 | elseif ws == 17, 9 | d = 2; 10 | elseif ws == 33; 11 | d = 4; 12 | elseif ws == 65, 13 | d = 8; 14 | end 15 | wswidth = floor(ws/2); 16 | 17 | % % calculate total variance, for window 9*9, it's 1080 18 | % [z1 z2]= find(map1); 19 | % z = [z1,z2]; 20 | % for i = 1:length(z1), 21 | % MM = mean(z); 22 | % m2 = repmat(MM, length(z), 1); 23 | % St = sum(diag(sqdist(z', m2'))); 24 | % end 25 | 26 | % truncate the border area of the original class map image 27 | % J-image 28 | JI = zeros(m,n); 29 | % for each pixel inside, calculate its J value in the window size 30 | for i = 1:m, 31 | for j = 1:n, 32 | x1 = i-wswidth; 33 | x2 = i+wswidth; 34 | y1 = j-wswidth; 35 | y2 = j+wswidth; 36 | if x1<1, 37 | x1 = 1; 38 | end 39 | if x2>m, 40 | x2 = m; 41 | end 42 | if y1<1, 43 | y1 = 1; 44 | end 45 | if y2>n, 46 | y2 = n; 47 | end 48 | wid = x2-x1+1; 49 | hei = y2-y1+1; 50 | if wid == ws && hei == ws, 51 | % median of the window, because of sampling, M won't change, neither St 52 | St = 1080; 53 | M = [5, 5]; 54 | else 55 | reg = ones(wid, hei); 56 | reg = reg(1:d:end, 1:d:end); 57 | [wid, hei] = size(reg); 58 | M = [mean(1:wid), mean(1:hei)]; 59 | [z1, z2] = find(reg); 60 | z = [z1, z2]; 61 | St = sum(sqdist(z', M')); 62 | end 63 | block = zeros(ws, ws); 64 | block = I(x1:x2, y1:y2); 65 | Jvalue = JCalculation(block(1:d:end, 1:d:end), M, St); 66 | JI(i,j) = Jvalue; 67 | end 68 | end 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /docde/ValleyD.m: -------------------------------------------------------------------------------- 1 | function ValleyI = ValleyD(JI, scale, uj, sj) 2 | 3 | [m, n] = size(JI); 4 | a = [-0.6, -0.4, -0.2, 0, 0.2, 0,4]; 5 | % valley size has to be larger than minsize under scale 1-4. 6 | minsize = [32, 128, 512, 2048]; 7 | % try a value one by one to find the value gives the most number of valleys 8 | scale = minsize(scale); 9 | MaxVSize = 0; 10 | ValleyI = zeros(m,n); 11 | for i = 1:length(a), 12 | TJ = uj + a(i)*sj; 13 | % candidate valley point (< TJ) == 1; 14 | VP = false(m,n); 15 | VP(JI <= TJ) = 1; 16 | % 4-connectivity => candidate valley (large size segments with low J 17 | % value 18 | VP_lab = bwlabel(VP,4); 19 | VPlab_hist = histc(VP_lab(:),1:max(VP_lab(:))); 20 | sq = find(VPlab_hist>=scale); 21 | VSize = length(sq); 22 | if length(sq)>MaxVSize 23 | ValleyI = zeros(m, n); 24 | for k = 1:length(sq) 25 | ValleyI(VP_lab==sq(k))=k; 26 | end 27 | MaxVSize = VSize; 28 | end 29 | end 30 | 31 | 32 | % 33 | % 34 | % 35 | % [m, n] = size(JI); 36 | % % valley size has to be larger than minsize under scale 1-4. 37 | % minsize = [32, 128, 512, 2048]; 38 | % % threshold UJ+a*SJ; 39 | % % try a value one by one to find the value gives the most number of valleys 40 | % VP = zeros(m, n); 41 | % scale = minsize(scale); 42 | % % maximum valley size with different a value 43 | % MaxVSize = 0; 44 | % ValleyI = zeros(m,n); 45 | % for i = 1:length(a), 46 | % SI = zeros(m, n); 47 | % TJ = uj + a(i)*sj; 48 | % % candidate valley point (< TJ) == 1; 49 | % [x, y] = find(JI <= TJ); 50 | % for j = 1:length(x), 51 | % VP(x(j), y(j)) = 1; 52 | % end 53 | % % 4-connectivity => candidate valley (large size segments with low J 54 | % % value 55 | % SI = SeedGrowing(VP,x,y, scale); 56 | % VSize = max(SI(:)); 57 | % if VSize > MaxVSize, 58 | % ValleyI = SI; 59 | % MaxVSize = VSize; 60 | % end 61 | % end 62 | 63 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /docde/SeedGrowing.m: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | function Seg = SeedGrowing(BI,seed_x,seed_y, minsize) 5 | 6 | [m,n] = size(BI); 7 | % output segments 8 | Seg = zeros(m, n); 9 | NumV = 0; 10 | % flag image (find which pixel is processed) 11 | J = ones(m, n); 12 | 13 | % 3 is the neighbour size 14 | x_direction = [-1, 0, 1, 0]; 15 | y_direction = [ 0, 1, 0, -1]; 16 | 17 | for i = 1:length(seed_x) 18 | if(J(seed_x(i), seed_y(i))==0) 19 | continue; 20 | else 21 | seedx = zeros(m*n, 1); 22 | seedy = zeros(m*n, 1); 23 | nStart = 1; 24 | nEnd = 1; 25 | seedx(1) = seed_x(i); 26 | seedy(1) = seed_y(i); 27 | J(seed_x(i),seed_y(i)) = 0; 28 | while(nStart <= nEnd), 29 | current_x = seedx(nStart); 30 | current_y = seedy(nStart); 31 | for k = 1:4, 32 | current_xx = current_x + x_direction(k); 33 | current_yy = current_y + y_direction(k); 34 | if (current_xx > 0 && current_xx < m ... 35 | && current_yy > 0 && current_yy < n ) 36 | if(BI(current_xx, current_yy) == 1 && J(current_xx, current_yy) ==1) 37 | J(current_xx, current_yy) = 0; 38 | nEnd = nEnd + 1; 39 | seedx(nEnd) = current_xx; 40 | seedy(nEnd) = current_yy; 41 | end 42 | end 43 | end 44 | nStart = nStart + 1; 45 | end 46 | end 47 | 48 | % % draw the segments dynamically 49 | % temp = zeros(m,n); 50 | % for i = 1:length(seedx), 51 | % if(seedx(i)~=0 && seedy(i) ~=0) 52 | % temp(seedx(i), seedy(i)) = 255; 53 | % end 54 | % end 55 | % imshow(temp); 56 | % hold on; 57 | % pause(2) 58 | 59 | if nEnd > minsize, 60 | NumV = NumV + 1; 61 | for i = 1:length(seedx), 62 | if(seedx(i)~=0 && seedy(i) ~=0) 63 | Seg(seedx(i), seedy(i)) = NumV; 64 | end 65 | end 66 | end 67 | end 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /docde/RegionMerge.m: -------------------------------------------------------------------------------- 1 | function Region = RegionMerge(IRGB,Imap, ImgS, outseg) 2 | 3 | IRGB = double(IRGB); 4 | segnum = max(ImgS(:)); 5 | qlv = max(Imap(:)); 6 | 7 | nhist = zeros(qlv,segnum); 8 | [row,col] = size(ImgS); 9 | for r = 1:row 10 | for j = 1:col 11 | rgind = ImgS(r,j); 12 | mapind = Imap(r,j); 13 | nhist(mapind,rgind) = nhist(mapind,rgind)+1; 14 | end 15 | end 16 | 17 | LUT = PNN_fast(ImgS,nhist, outseg); 18 | % LUT = PNN_fast_RGBo(ImgS,IRGB, outseg); 19 | 20 | Region = LUT(ImgS); 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | % 30 | % 31 | % 32 | % [m, n, d] = size(Iq); 33 | % Iq = uint8(Iq); 34 | % % quantized color value and number 35 | % QCvalue = zeros(d, Cno); 36 | % for dd = 1:d, 37 | % if(length(unique(Iq(:,:,dd))) == Cno), 38 | % QCvalue(dd, :) = unique(Iq(:,:,dd)); 39 | % else 40 | % zvalue = zeros(1, Cno-length(unique(Iq(:,:,dd)))); 41 | % QCvalue(dd, :) = [zvalue'; unique(Iq(:,:,dd))]; 42 | % end 43 | % end 44 | % Cno = Cno*d; 45 | % 46 | % % region number 47 | % Rno = max(ImgS(:)); 48 | % % region color information data 49 | % % RC -- the histogram data Rno*Cno for clustering input 50 | % RC = zeros(Rno, Cno); 51 | % for i = 1:max(ImgS(:)), 52 | % Hist = zeros(d, Cno/d); 53 | % Color = zeros(m, n, d); 54 | % sq = find(ImgS == i); 55 | % Color(sq) = Iq(sq); 56 | % for dim = 1:d, 57 | % Channel = Color(:,:,dim); 58 | % a = hist(Channel(:), QCvalue(dim, :)); 59 | % Hist(dim, :) = a; 60 | % end 61 | % Hist = reshape(Hist, 1, Cno); 62 | % RC(i, :) = Hist; 63 | % end 64 | % 65 | % % calculate distances between regions 66 | % % d channels, sqrt(Dist1+Dist2+Distd) 67 | % 68 | % ADist = zeros(1, Rno*(Rno-1)/2); 69 | % for dim = 1:d, 70 | % % each channel: Rno*Cno 71 | % RCd = RC(:,dim:d:end); 72 | % Dist = pdist(RCd); 73 | % ADist = ADist + power(Dist, 2); 74 | % end 75 | % ADist = sqrt(ADist); 76 | % 77 | % % single linkage clustering, merge two 78 | % Z = linkage(ADist); 79 | % T = cluster(Z,'maxclust',threshold ); 80 | % 81 | % Channel = ImgS; 82 | % for t = 1:Rno, 83 | % xy = find(Channel == t); 84 | % ImgS(xy) = T(t); 85 | % end 86 | % 87 | % I = ImgS; 88 | % % fprintf('%d\n', max(I(:))); 89 | % 90 | % 91 | % 92 | 93 | 94 | 95 | -------------------------------------------------------------------------------- /docde/RegionMerge_RGB.m: -------------------------------------------------------------------------------- 1 | function Region = RegionMerge_RGB(IRGB,Imap, ImgS, outseg) 2 | 3 | IRGB = double(IRGB); 4 | segnum = max(ImgS(:)); 5 | qlv = max(Imap(:)); 6 | 7 | nhist = zeros(qlv,segnum); 8 | [row,col] = size(ImgS); 9 | for r = 1:row 10 | for j = 1:col 11 | rgind = ImgS(r,j); 12 | mapind = Imap(r,j); 13 | nhist(mapind,rgind) = nhist(mapind,rgind)+1; 14 | end 15 | end 16 | 17 | % LUT = PNN_fast(ImgS,nhist, outseg); 18 | LUT = PNN_fast_RGBo(ImgS,IRGB, outseg); 19 | 20 | Region = LUT(ImgS); 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | % 30 | % 31 | % 32 | % [m, n, d] = size(Iq); 33 | % Iq = uint8(Iq); 34 | % % quantized color value and number 35 | % QCvalue = zeros(d, Cno); 36 | % for dd = 1:d, 37 | % if(length(unique(Iq(:,:,dd))) == Cno), 38 | % QCvalue(dd, :) = unique(Iq(:,:,dd)); 39 | % else 40 | % zvalue = zeros(1, Cno-length(unique(Iq(:,:,dd)))); 41 | % QCvalue(dd, :) = [zvalue'; unique(Iq(:,:,dd))]; 42 | % end 43 | % end 44 | % Cno = Cno*d; 45 | % 46 | % % region number 47 | % Rno = max(ImgS(:)); 48 | % % region color information data 49 | % % RC -- the histogram data Rno*Cno for clustering input 50 | % RC = zeros(Rno, Cno); 51 | % for i = 1:max(ImgS(:)), 52 | % Hist = zeros(d, Cno/d); 53 | % Color = zeros(m, n, d); 54 | % sq = find(ImgS == i); 55 | % Color(sq) = Iq(sq); 56 | % for dim = 1:d, 57 | % Channel = Color(:,:,dim); 58 | % a = hist(Channel(:), QCvalue(dim, :)); 59 | % Hist(dim, :) = a; 60 | % end 61 | % Hist = reshape(Hist, 1, Cno); 62 | % RC(i, :) = Hist; 63 | % end 64 | % 65 | % % calculate distances between regions 66 | % % d channels, sqrt(Dist1+Dist2+Distd) 67 | % 68 | % ADist = zeros(1, Rno*(Rno-1)/2); 69 | % for dim = 1:d, 70 | % % each channel: Rno*Cno 71 | % RCd = RC(:,dim:d:end); 72 | % Dist = pdist(RCd); 73 | % ADist = ADist + power(Dist, 2); 74 | % end 75 | % ADist = sqrt(ADist); 76 | % 77 | % % single linkage clustering, merge two 78 | % Z = linkage(ADist); 79 | % T = cluster(Z,'maxclust',threshold ); 80 | % 81 | % Channel = ImgS; 82 | % for t = 1:Rno, 83 | % xy = find(Channel == t); 84 | % ImgS(xy) = T(t); 85 | % end 86 | % 87 | % I = ImgS; 88 | % % fprintf('%d\n', max(I(:))); 89 | % 90 | % 91 | % 92 | 93 | 94 | 95 | -------------------------------------------------------------------------------- /RegionMerging.m: -------------------------------------------------------------------------------- 1 | function RegionResult=RegionMerging(image,Region,mnadj,RMThresh) 2 | %% Written by Muhammet Balcilar, France 3 | % all rights reverved 4 | 5 | 6 | 7 | %% main bloc of algorithm 8 | 9 | % find which rregions are connected to each other 10 | [N Con]=findNeighbour(Region,mnadj); 11 | 12 | % find every regions sttistci which means means and covariances 13 | Stat=findStatistic(Region,image); 14 | 15 | % calculate initial regions S similarity values 16 | Sval=calcSval(Stat,Con); 17 | 18 | % separate R,G, and B channel of image 19 | R=image(:,:,1); 20 | G=image(:,:,2); 21 | B=image(:,:,3); 22 | R=double(R(:)); 23 | G=double(G(:)); 24 | B=double(B(:)); 25 | 26 | % while minimum similarity of connected regions are still less than given 27 | % certain threshold continue the process 28 | while min(Sval) 0 && x<=m && y > 0 && y <=n, 39 | 40 | if BRegion(x, y) == 0, 41 | P = x + m*(y-1); 42 | J = JI(x,y); 43 | [hp,hpid] = heap_add(hp,hpid,J,P); 44 | BRegion(x,y) = curval; 45 | % else 46 | % Region(pos) = Region(P); 47 | end 48 | end 49 | end 50 | end 51 | 52 | 53 | 54 | 55 | % % [B,L] = bwboundaries(imdilate(Region, [0 1 0; 1 1 1; 0 1 0]), 'noholes'); 56 | % % 57 | % % for k = 1:length(B), 58 | % % boundary = B{k}; 59 | % % % J value on outer boundaries 60 | % % Jb = []; 61 | % % for b = 1:size(boundary,1), 62 | % % Jb = [Jb JI(boundary(b,1), boundary(b,2))]; 63 | % % end 64 | % % [v, id] = min(Jb); 65 | % % %the pixel with minimum J value 66 | % % Jbmin = boundary(id, :); 67 | % % % assgign to the adjacent segment, values from 4-connectivity neighbour 68 | % % temp = []; 69 | % % x_direction = [-1, 0, 1, 0]; 70 | % % y_direction = [ 0, 1, 0, -1]; 71 | % % for k = 1:4, 72 | % % x = Jbmin(1) + x_direction(k); 73 | % % y = Jbmin(2) + y_direction(k); 74 | % % temp = [temp Region(x, y)]; 75 | % % end 76 | % % if length(unique(temp(find(temp ~= 0)))) == 1, 77 | % % Region(Jbmin(1), Jbmin(2)) = unique(temp(find(temp ~=0))); 78 | % % else 79 | % % break; 80 | % % end 81 | % % end 82 | end 83 | 84 | SegI = Region; 85 | 86 | % ShowSegs(SegI); 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /docde/ssim_index.m: -------------------------------------------------------------------------------- 1 | function [mssim, ssim_map] = ssim_index(img1, img2, K, window, L) 2 | 3 | 4 | if (nargin < 2 || nargin > 5) 5 | ssim_index = -Inf; 6 | ssim_map = -Inf; 7 | return; 8 | end 9 | 10 | if (size(img1) ~= size(img2)) 11 | ssim_index = -Inf; 12 | ssim_map = -Inf; 13 | return; 14 | end 15 | 16 | [M N] = size(img1); 17 | 18 | if (nargin == 2) 19 | if ((M < 11) || (N < 11)) 20 | ssim_index = -Inf; 21 | ssim_map = -Inf; 22 | return 23 | end 24 | window = fspecial('gaussian', 11, 1.5); % 25 | K(1) = 0.01; % default settings 26 | K(2) = 0.03; % 27 | L = 255; % 28 | end 29 | 30 | if (nargin == 3) 31 | if ((M < 11) || (N < 11)) 32 | ssim_index = -Inf; 33 | ssim_map = -Inf; 34 | return 35 | end 36 | window = fspecial('gaussian', 11, 1.5); 37 | L = 255; 38 | if (length(K) == 2) 39 | if (K(1) < 0 || K(2) < 0) 40 | ssim_index = -Inf; 41 | ssim_map = -Inf; 42 | return; 43 | end 44 | else 45 | ssim_index = -Inf; 46 | ssim_map = -Inf; 47 | return; 48 | end 49 | end 50 | 51 | if (nargin == 4) 52 | [H W] = size(window); 53 | if ((H*W) < 4 || (H > M) || (W > N)) 54 | ssim_index = -Inf; 55 | ssim_map = -Inf; 56 | return 57 | end 58 | L = 255; 59 | if (length(K) == 2) 60 | if (K(1) < 0 || K(2) < 0) 61 | ssim_index = -Inf; 62 | ssim_map = -Inf; 63 | return; 64 | end 65 | else 66 | ssim_index = -Inf; 67 | ssim_map = -Inf; 68 | return; 69 | end 70 | end 71 | 72 | if (nargin == 5) 73 | [H W] = size(window); 74 | if ((H*W) < 4 || (H > M) || (W > N)) 75 | ssim_index = -Inf; 76 | ssim_map = -Inf; 77 | return 78 | end 79 | if (length(K) == 2) 80 | if (K(1) < 0 || K(2) < 0) 81 | ssim_index = -Inf; 82 | ssim_map = -Inf; 83 | return; 84 | end 85 | else 86 | ssim_index = -Inf; 87 | ssim_map = -Inf; 88 | return; 89 | end 90 | end 91 | 92 | C1 = (K(1)*L)^2; 93 | C2 = (K(2)*L)^2; 94 | window = window/sum(sum(window)); 95 | img1 = double(img1); 96 | img2 = double(img2); 97 | 98 | mu1 = filter2(window, img1, 'valid'); 99 | mu2 = filter2(window, img2, 'valid'); 100 | mu1_sq = mu1.*mu1; 101 | mu2_sq = mu2.*mu2; 102 | mu1_mu2 = mu1.*mu2; 103 | sigma1_sq = filter2(window, img1.*img1, 'valid') - mu1_sq; 104 | sigma2_sq = filter2(window, img2.*img2, 'valid') - mu2_sq; 105 | sigma12 = filter2(window, img1.*img2, 'valid') - mu1_mu2; 106 | 107 | if (C1 > 0 & C2 > 0) 108 | ssim_map = ((2*mu1_mu2 + C1).*(2*sigma12 + C2))./((mu1_sq + mu2_sq + C1).*(sigma1_sq + sigma2_sq + C2)); 109 | else 110 | numerator1 = 2*mu1_mu2 + C1; 111 | numerator2 = 2*sigma12 + C2; 112 | denominator1 = mu1_sq + mu2_sq + C1; 113 | denominator2 = sigma1_sq + sigma2_sq + C2; 114 | ssim_map = ones(size(mu1)); 115 | index = (denominator1.*denominator2 > 0); 116 | ssim_map(index) = (numerator1(index).*numerator2(index))./(denominator1(index).*denominator2(index)); 117 | index = (denominator1 ~= 0) & (denominator2 == 0); 118 | ssim_map(index) = numerator1(index)./denominator1(index); 119 | end 120 | 121 | mssim = mean2(ssim_map); 122 | 123 | return -------------------------------------------------------------------------------- /docde/ValleyG1.m: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | function SegI = ValleyG1(JI, ValleyI) 5 | % valley growing: new regions grow from the valleys 6 | % RemainI: 0 means processed; non-0 means remaining 7 | %% revise by Minjie 8 | [m, n] = size(ValleyI); 9 | 10 | % step1. remove the holes 11 | 12 | ValleyI = imfill(ValleyI, 'holes'); 13 | SegI = ValleyI; 14 | 15 | % step2. for the remaining unsegmented part 16 | sq_remain = find(ValleyI == 0); 17 | JIhigh = JI(sq_remain); 18 | u = mean(JIhigh); 19 | sq_medth = sq_remain(JIhigh0); 37 | SegI(sq) = tmp; 38 | end 39 | end 40 | 41 | %% 42 | % [m, n] = size(ValleyI); 43 | % 44 | % % step1. remove the holes by morphological filtering 45 | % se = strel('square',3); 46 | % ValleyI = imclose(ValleyI, se); 47 | % 48 | % SegI = ValleyI; 49 | % 50 | % % step2. for the remaining unsegmented part 51 | % sq_remain = find(ValleyI == 0); 52 | % JIhigh = JI(sq_remain); 53 | % u = mean(JIhigh); 54 | % sq_medth = sq_remain(JIhigh minsize, 86 | % % for s = 1:length(gx), 87 | % % RemainI(gx(s), gy(s)) = RemainI(gx(s), gy(s)) + max(SegI(:)); 88 | % % end 89 | % % SegI = SegI + RemainI; 90 | % % end 91 | % % end 92 | % end 93 | % 94 | % 95 | % % RemainI = zeros(m,n); 96 | % % [x, y] = find(ValleyI == 0); 97 | % % for i = 1:length(x), 98 | % % RemainI(x(i), y(i)) = JI(x(i), y(i)); 99 | % % end 100 | % 101 | % % u = sum(RemainI(:))/length(x); 102 | % 103 | % % get the image part under u in the remaining part, region grow 104 | % 105 | % 106 | % % region grow 107 | % % GArea = SeedGrowing(GArea, gx, gy, 1); 108 | % % bw_GArea = bwlabel(logical(GArea),4); 109 | % % % dilation on the ValleyI 110 | % % se1 = strel('diamond',1); 111 | % % bw_GAread = imdilate(bw_GArea, se1); 112 | % 113 | % 114 | % 115 | % 116 | % 117 | % 118 | % 119 | 120 | 121 | 122 | -------------------------------------------------------------------------------- /docde/Evaluation.m: -------------------------------------------------------------------------------- 1 | % clear all 2 | clc 3 | 4 | filename = ['124084']; 5 | image_org = imread(filename); 6 | [m,n,d] = size(image_org); 7 | % figure; imshow(image_org); 8 | 9 | % class_map from clustering algorithms 10 | pa_filename = ['woman6.pa']; 11 | PA = load(pa_filename); 12 | if length(PA) == m*n %&& length(find(PA==0))~=0, 13 | map = reshape(PA, m, n); 14 | map = map+1; 15 | else 16 | fprintf('something wrong!!\n'); 17 | end 18 | 19 | % % generate J images 20 | for w = 1:4, 21 | W = GenerateWindow(w); 22 | JI = JImage(map, W); 23 | save([num2str(w) '.mat'], 'JI'); 24 | % imwrite(JI, ['JImage' num2str(w) '.jpg']); 25 | end 26 | 27 | 28 | load('4.mat'); 29 | JI4 = JI; 30 | load('3.mat'); 31 | JI3 = JI; 32 | load('2.mat'); 33 | JI2 = JI; 34 | load('1.mat'); 35 | JI1 = JI; 36 | 37 | % quantized image 38 | ImgQ = class2Img(map, image_org); 39 | 40 | Region = zeros(m, n); 41 | % --------------------scale 4-------------------- 42 | % scale 4 43 | u = mean(JI4(:)); 44 | s = std(JI4(:)); 45 | Region = ValleyD(JI4, 4, u, s); % 4.1 Valley Determination 46 | Region = ValleyG1(JI4, Region); % 4.2.2 Growing 47 | Region = ValleyG1(JI3, Region); % 4.2.3 Growing at next smaller scale 48 | Region = ValleyG2(JI1, Region); % 4.2.4 remaining pixels at the smallest scale 49 | Region4 = Region; 50 | fprintf('scale4: %d\n', max(Region(:))); 51 | % draw segments 52 | figure; imshow(uint8(ImgQ)); 53 | hold on; 54 | DrawLine(Region); 55 | hold off; 56 | % --------------------scale 3-------------------- 57 | w = 3; 58 | Region = SpatialSeg(JI3, Region, w); 59 | % Valley Growing at the next smaller scale level 60 | Region = ValleyG1(JI2, Region); 61 | % Valley Growing at the smallest scale level 62 | Region = ValleyG2(JI1, Region); 63 | Region3 = Region; 64 | fprintf('scale3: %d\n', max(Region(:))); 65 | figure; imshow(uint8(ImgQ)); 66 | hold on; 67 | DrawLine(Region); 68 | hold off; 69 | % --------------------scale 2-------------------- 70 | % SpatialSeg includes one ValleyD and ValleyG1 at current scale level 71 | w = 2; 72 | Region = SpatialSeg(JI2, Region, w); 73 | % Valley Growing at the next smaller scale level 74 | Region = ValleyG1(JI1, Region); 75 | % Valley Growing at the smallest scale level 76 | Region = ValleyG2(JI1, Region); 77 | Region2 = Region; 78 | fprintf('scale2: %d\n', max(Region(:))); 79 | figure; imshow(uint8(ImgQ)); 80 | hold on; 81 | DrawLine(Region); 82 | hold off; 83 | 84 | % % % % % % --------------------scale 1-------------------- 85 | w = 1; 86 | Region = SpatialSeg(JI1, Region, w); 87 | Region = ValleyG2(JI1, Region); 88 | Region1 = Region; 89 | fprintf('scale1: %d\n', max(Region(:))); 90 | figure; imshow(uint8(ImgQ)); 91 | hold on; 92 | DrawLine(Region); 93 | hold off; 94 | 95 | % determining the number of segments 96 | index = []; 97 | for t = 2:10, 98 | Region0 = RegionMerge_RGB(image_org, map, Region, t); 99 | [Einter, Eintra, Score] = Fratio(image_org, Region0); 100 | index = [index; Score]; 101 | end 102 | 103 | % plot the "optimal" segmentation 104 | [seg_no index_value] = min[index]; 105 | seg_no = seg_no + 1; 106 | Region0 = RegionMerge_RGB(image_org, map, Region, seg_no); 107 | figure; imshow(uint8(ImgQ)); 108 | hold on; 109 | DrawLine(Region0); 110 | hold off; 111 | 112 | -------------------------------------------------------------------------------- /docde/kmeansO.m: -------------------------------------------------------------------------------- 1 | function [Er,M, nb, P] = kmeansO(X,T,kmax,dyn,bs, killing, pl) 2 | 3 | Er=[]; TEr=[]; % error monitorring 4 | 5 | [n,d] = size(X); 6 | P = zeros(n,1); 7 | 8 | THRESHOLD = 1e-4; % relative change in error that is regarded as convergence 9 | nb = 0; 10 | 11 | % initialize 12 | if dyn==1 % greedy insertion, possible at all points 13 | k = 1; 14 | M = mean(X); 15 | K = sqdist(X',X'); 16 | L = X; 17 | elseif dyn==2 % use kd-tree results as means 18 | k = kmax; 19 | M = kdtree(X,[1:n]',[],1.5*n/k); 20 | nb = size(M,1); 21 | dyn = 0; 22 | elseif dyn==3 23 | L = kdtree(X,[1:n]',[],1.5*n/bs); 24 | nb = size(L,1); 25 | k = 1; 26 | M = mean(X); 27 | K = sqdist(X',L'); 28 | elseif dyn==4 29 | k = 1; 30 | M = mean(X); 31 | K = sqdist(X',X'); 32 | L = X; 33 | else % use random subset of data as means 34 | k = kmax; 35 | tmp = randperm(n); 36 | M = X(tmp(1:k),:); 37 | end 38 | 39 | Wold = realmax; 40 | 41 | while k <= kmax 42 | kill = []; 43 | 44 | % squared Euclidean distances to means; Dist (k x n) 45 | Dist = sqdist(M',X'); 46 | 47 | % Voronoi partitioning 48 | [Dwin,Iwin] = min(Dist',[],2); 49 | P = Iwin; 50 | 51 | % error measures and mean updates 52 | Wnew = sum(Dwin); 53 | 54 | % update VQ's 55 | for i=1:size(M,1) 56 | I = find(Iwin==i); 57 | if size(I,1)>d 58 | M(i,:) = mean(X(I,:)); 59 | elseif killing==1 60 | kill = [kill; i]; 61 | end 62 | end 63 | 64 | if 1-Wnew/Wold < THRESHOLD*(10-9*(k==kmax)) 65 | if dyn & k < kmax 66 | 67 | if dyn == 4 68 | best_Er = Wnew; 69 | 70 | for i=1:n; 71 | Wold = Inf; 72 | Wtmp = Wnew; 73 | Mtmp = [M; X(i,:)]; 74 | while (1-Wtmp/Wold) > THRESHOLD*10; 75 | Wold = Wtmp; 76 | Dist = sqdist(Mtmp',X'); 77 | [Dwin,Iwin] = min(Dist',[],2); 78 | Wtmp = sum(Dwin); 79 | for i = 1 : size(Mtmp,1) 80 | I = find(Iwin==i); 81 | if size(I,1)>d; Mtmp(i,:) = mean(X(I,:)); end 82 | end 83 | end 84 | if Wtmp < best_Er; best_M = Mtmp; best_Er = Wtmp; end 85 | end 86 | 87 | M = best_M; 88 | Wnew = best_Er; 89 | if ~isempty(T); tmp=sqdist(T',M'); TEr=[TEr; sum(min(tmp,[],2))];end; 90 | Er=[Er; Wnew]; 91 | k = k+1; 92 | 93 | else 94 | % try to add a new cluster on some point x_i 95 | [tmp,new] = max(sum(max(repmat(Dwin,1,size(K,2))-K,0))); 96 | k = k+1; 97 | M = [M; L(new,:)+eps]; 98 | if pl; fprintf( 'new cluster, k=%d\n', k); end 99 | [Dwin,Iwin] = min(Dist',[],2); 100 | Wnew = sum(Dwin);Er=[Er; Wnew]; 101 | if ~isempty(T); tmp=sqdist(T',M'); TEr=[TEr; sum(min(tmp,[],2))];end; 102 | end 103 | else 104 | k = kmax+1; 105 | end 106 | end 107 | Wold = Wnew; 108 | if pl 109 | figure(1); plot(X(:,1),X(:,2),'g.',M(:,1),M(:,2),'k.',M(:,1),M(:,2),'k+'); 110 | drawnow; 111 | end 112 | end 113 | 114 | Er=[Er; Wnew]; 115 | if ~isempty(T); tmp=sqdist(T',M'); TEr=[TEr; sum(min(tmp,[],2))]; Er=[Er TEr];end; 116 | M(kill,:)=[]; 117 | 118 | -------------------------------------------------------------------------------- /docde/SegEval.m: -------------------------------------------------------------------------------- 1 | function ScorePlot(feature_file, partition_file, loglk_file) 2 | clc 3 | % close all 4 | % PlotStyles = {'*-r','o-g','x-m','+-k'}; 5 | % for no = 1:4, 6 | feature_file = 'tree.txt'; 7 | 8 | % for BIC 9 | d = 3; 10 | loglk_file = 'loglk.txt'; 11 | loglikelihood = load(loglk_file); 12 | BIC_VALUE = []; 13 | for j = 2:60, 14 | partition_file = ['tree_' num2str(j) '.txt']; 15 | BICvalue = SegBIC(partition_file, loglikelihood(j-1), d); 16 | BIC_VALUE = [BIC_VALUE, BICvalue]; 17 | end 18 | % plot(2:60, BIC_VALUE, '*-g'); 19 | % grid on; 20 | % end BIC 21 | BIC_min = min(BIC_VALUE); 22 | BIC_max = max(BIC_VALUE); 23 | Norm_BIC = (BIC_VALUE-BIC_min)/(BIC_max-BIC_min); 24 | plot(2:60, Norm_BIC, '*-g'); 25 | hold on; grid on; 26 | % wb-index 27 | Score_Matrix = []; 28 | for i = 2: 60, 29 | partition_file = ['tree_' num2str(i) '.txt']; 30 | Score = SegEvaluate(feature_file, partition_file); 31 | Score_Matrix = [Score_Matrix, Score]; 32 | end 33 | [value,num] = min(Score_Matrix); 34 | % disp(num); 35 | % figure; 36 | % plot(2:60, Score_Matrix, '*-b'); 37 | % grid on; 38 | 39 | % end wb-index 40 | wb_min = min(Score_Matrix); 41 | wb_max= max(Score_Matrix); 42 | norm_wb = (Score_Matrix-wb_min)/(wb_max-wb_min); 43 | plot(2:60, norm_wb, 'o-r'); 44 | plot(2:60, Norm_BIC+ norm_wb, '*-r'); 45 | [a,b] = min(Norm_BIC+ norm_wb); 46 | disp(b); 47 | hold on; 48 | 49 | % end 50 | % this function is used to evaluate the image segmentation results. 51 | % input: feature file; 52 | % label file with partitions 53 | % output: value indicate the evaluation 54 | % by Qinpei zhao 10.Mar.2009 55 | % N - the number of data points (pixel number) 56 | % d - dimension of feature space 57 | % M - number of components 58 | % Nj- number of pixels in each component 59 | % NB: not applicable for M = 1; 1 component doesn't need to evaluate!!!! 60 | function Score = SegEvaluate(feature_file, partition_file) 61 | Score = 0; 62 | Label = load(partition_file); 63 | M = max(Label) + 1; 64 | Feature = load(feature_file); 65 | [N,d] = size(Feature); 66 | % assume each dimension of features is independent 67 | for dim = 1:d, 68 | ssw = 0; 69 | ssb = 0; 70 | % mean of the whole image on each feature 71 | Xmean = sum(Feature(:, dim)); 72 | for m = 0: M-1, 73 | Index = find(Label == m); 74 | Nm = length(Index); 75 | Cmean = sum(Feature(Index, dim)); 76 | temp = Feature(Index, dim)-Cmean; 77 | ssw = ssw + sum(sqrt(temp.*temp)); 78 | ssb = ssb + Nm* sqrt((Cmean - Xmean)*(Cmean - Xmean)); 79 | end 80 | Score = Score + ssw / ssb; 81 | 82 | end 83 | Score = M*Score; 84 | 85 | 86 | % evaluate by BIC = -loglikelihood + 0.5*k*sum(log(Ni)) 87 | % input: partition_file 88 | % loglikelihood 89 | % output: BIC value 90 | 91 | function BICvalue = SegBIC(partition_file, loglikelihood, dim) 92 | Label = load(partition_file); 93 | N = length(Label); 94 | M = max(Label) + 1; 95 | temp = 0; 96 | for m = 0:M-1, 97 | Index = find(Label == m); 98 | % number of points for each component 99 | Nm = length(Index); 100 | temp = temp + log(Nm); 101 | end 102 | 103 | BICvalue = -N*loglikelihood + 0.5*M*(dim+1)*temp; 104 | 105 | 106 | 107 | 108 | -------------------------------------------------------------------------------- /docde/PNN_fast.m: -------------------------------------------------------------------------------- 1 | function T = PNN_fast(Iseg,nhist,nseg) 2 | 3 | n = size(nhist,2); 4 | conn = diag(ones(1,n)); 5 | 6 | %get boundary conn 7 | [row,col] = size(Iseg); 8 | diffx = diff(Iseg,1,2); 9 | diffy = diff(Iseg,1,1); 10 | sq1 = find(diffx); 11 | sq2 = find(diffy); 12 | for t = 1:length(sq1) 13 | v1 = Iseg(sq1(t)); 14 | v2 = Iseg(sq1(t)+ row); 15 | conn(v1,v2) = 1; 16 | conn(v2,v1) = 1; 17 | end 18 | for t = 1:length(sq2) 19 | v1 = Iseg(sq2(t)); 20 | v2 = Iseg(sq2(t)+ 1); 21 | conn(v1,v2) = 1; 22 | conn(v2,v1) = 1; 23 | end 24 | 25 | 26 | histnum = sum(nhist,1); 27 | qlv = size(nhist,1); 28 | tmp = repmat(histnum,qlv,1); 29 | phist = nhist./tmp; 30 | %dist between phist 31 | distv = pdist(phist','euclidean');%probably KL distance is a better choice, use method in the paper here. 32 | %also, original image's mean RGB value can be considered. 33 | distv = distv.^2; 34 | distv = squareform(distv); 35 | Y = distv; 36 | Y(conn==0)= inf; 37 | 38 | minY_col = zeros(1,n); 39 | minY_colsq = zeros(1,n); 40 | for i = 1:n 41 | j1 = 1:(i-1); 42 | j2 = (i+1):n; 43 | jtmp = [j1 j2]; 44 | ytmp = Y(i,jtmp); 45 | [tmp1,tmp2] = min(ytmp); 46 | minY_col(i) = tmp1; 47 | minY_colsq(i) = jtmp(tmp2); 48 | end 49 | 50 | R = 1:n;%n: number of vector 51 | Z = zeros(n-1,3); % allocate the output matrix. 52 | % during updating clusters, cluster index is constantly changing, R is 53 | % a index vector mapping the original index to the current (row, column) 54 | % index in Y. N denotes how many points are contained in each cluster. 55 | N = zeros(1,2*n-1); 56 | N(1:n) = histnum; 57 | centers = zeros(2*n-1,qlv); 58 | centers(1:n,:) = phist'; 59 | 60 | for s = 1:(n-1) 61 | % [v, k] = min(Y); 62 | ncur = length(minY_col); 63 | [v, k] = min(minY_col); 64 | ctmp = k; 65 | rtmp = minY_colsq(k); 66 | 67 | Z(s,:) = [R(rtmp) R(ctmp) v]; % update one more row to the output matrix A 68 | if s