├── outdoor.jpg ├── FinalReport.pdf ├── README.md ├── MainSource.m ├── Segmentation.m └── CompressDecompress.m /outdoor.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/router/ImageSegmentation/master/outdoor.jpg -------------------------------------------------------------------------------- /FinalReport.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/router/ImageSegmentation/master/FinalReport.pdf -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ImageSegmentation 2 | ================= 3 | 4 | Effect of JPEG Compression on Image Segmentation Techniques 5 | -------------------------------------------------------------------------------- /MainSource.m: -------------------------------------------------------------------------------- 1 | %resetting workspace 2 | clear 3 | close all 4 | clc 5 | %end of resetting 6 | 7 | mainImage=imread('outdoor.jpg'); 8 | origImage=mainImage; 9 | imageDimensions=size(mainImage); 10 | greyImage=rgb2gray(mainImage); 11 | [outputImage,PSNR,CR]=CompressDecompress(mainImage,1); 12 | choice=input('Enter segmentation technique : \n 1:K-Means\n 2:Thresholding\n 3:Histogram baseed\n 4:Edge Detection\n'); 13 | Segmentation(outputImage,choice); 14 | 15 | 16 | -------------------------------------------------------------------------------- /Segmentation.m: -------------------------------------------------------------------------------- 1 | function [ ] = Segmentation( inputImage,option) 2 | 3 | switch option 4 | case 1 5 | KMeans(inputImage); 6 | case 2 7 | Threshold(inputImage); 8 | case 3 9 | Histogram(inputImage); 10 | case 4 11 | EdgeDetection(inputImage); 12 | 13 | otherwise 14 | display('Incorrect choice'); 15 | 16 | end 17 | 18 | 19 | end 20 | 21 | 22 | function [] = KMeans(inputImage) 23 | modImage = double(reshape(inputImage,size(inputImage,1)*size(inputImage,2),size(inputImage,3))); 24 | clusters= kmeans(modImage,5); 25 | figure('name','KMeans'); 26 | imagesc(reshape(clusters,size(inputImage,1),size(inputImage,2))); 27 | %imshow(inputImage) 28 | end 29 | 30 | 31 | function [] = Threshold(inputImage) %Using Otsu thresholding 32 | 33 | level = graythresh(inputImage); 34 | BW = im2bw(inputImage,level); 35 | figure(); 36 | imshow(BW); 37 | 38 | end 39 | 40 | 41 | function []=Histogram(inputImage) %Bimodal 42 | tempHist=hist(inputImage,256); 43 | histogram=sum(tempHist'); 44 | figure('name','Histogram Plot'); 45 | plot(tempHist,'r'); 46 | localMaxima=find(histogram==max(histogram)); 47 | bw=roicolor(inputImage,localMaxima,255); 48 | figure('name','Histogram Bitmap'); 49 | imshow(bw); 50 | end 51 | 52 | 53 | function []=EdgeDetection(inputImage) 54 | inputImage=im2double(inputImage); 55 | choice=input('Enter your choice :\n1:Prewitt\n2:Roberts\n3:Laplacian of a Guassian(LoG)\n'); 56 | filterOutput=[]; 57 | switch choice 58 | case 1 59 | filterOutput=edge(inputImage,'prewitt'); 60 | figure(); 61 | imshow(filterOutput); 62 | case 2 63 | filterOutput=edge(inputImage,'roberts'); 64 | figure(); 65 | imshow(filterOutput); 66 | case 3 67 | filterOutput=edge(inputImage,'log'); 68 | figure(); 69 | imshow(filterOutput); 70 | 71 | otherwise 72 | display('\nWrong Choice\n'); 73 | end 74 | end 75 | 76 | 77 | -------------------------------------------------------------------------------- /CompressDecompress.m: -------------------------------------------------------------------------------- 1 | function [ finalOutput PSNR CompressionRatio ] = CompressDecompress( mainImage,scaleFactor ) 2 | 3 | redValues=mainImage(:,:,1); 4 | greenValues=mainImage(:,:,2); 5 | blueValues=mainImage(:,:,3); 6 | yValues=0.299*(redValues-greenValues)+greenValues+0.114*(blueValues-greenValues); 7 | %figure(); 8 | %imshow(yValues); 9 | 10 | 11 | 12 | [rows columns numberOfColorBands] = size(mainImage); 13 | cropLimit=min(rows,columns); 14 | croppedImage = mainImage(1:cropLimit,1:cropLimit); 15 | scaleFactor=1024/cropLimit; 16 | scaledImage=imresize(croppedImage,scaleFactor); 17 | fi 18 | % imshow(scaledImage); 19 | 20 | defaultQuantizationMatrix = [ 21 | 16 11 10 16 24 40 51 61 22 | 12 12 14 19 26 58 60 55 23 | 14 13 16 24 40 57 69 56 24 | 14 17 22 29 51 87 80 62 25 | 18 22 37 56 68 109 103 77 26 | 24 35 55 64 81 104 113 92 27 | 49 64 78 87 103 121 120 101 28 | 72 92 95 98 112 100 103 99]; 29 | 30 | zigzagScanIndex=[11,12,21,31,22,13,14,23,32,41,51,42,33,24,15,16,25,34,43,52,61,71,62,53,44,35,26,17,18,27,36,45,54,63,72,81,82,73,64,55,46,37,28,38,47,56,65,74,83,84,75,66,57,48,58,67,76,85,86,77,68,78,87,88]; 31 | 32 | 33 | 34 | 35 | huffmanCodesDC={'00','010','011','100','101','110','1110','11110','111110','1111110','11111110','111111110'}; 36 | huffmanCodesAC={'00','01','100','1011','11010','1111000','11111000','1111110110','1111111110000010','1111111110000011'; 37 | '1100','11011','1111001','111110110','11111110110','1111111110000100','1111111110000101','1111111110000110','1111111110000111','1111111110001000'; 38 | '11100','11111001','1111110111','111111110100','1111111110001001','1111111110001010','1111111110001011','1111111110001100','1111111110001101','1111111110001110'; 39 | '111010','111110111','111111110101','1111111110001111','1111111110010000','1111111110010001','1111111110010010','1111111110010011','1111111110010100','1111111110010101'; 40 | '111011','1111111000','1111111110010110','1111111110010111','1111111110011000','1111111110011001','1111111110011010','1111111110011011','1111111110011100','1111111110011101'; 41 | '1111010','11111110111','1111111110011110','1111111110011111','1111111110100000','1111111110100001','1111111110100010','1111111110100011','1111111110100100','1111111110100101'; 42 | '1111011','111111110110','1111111110100110','1111111110100111','1111111110101000','1111111110101001','1111111110101010','1111111110101011','1111111110101100','1111111110101101'; 43 | '11111010','111111110111','1111111110101110','1111111110101111','1111111110110000','1111111110110001','1111111110110010','1111111110110011','1111111110110100','1111111110110101'; 44 | '111111000','111111111000000','1111111110110110','1111111110110111','1111111110111000','1111111110111001','1111111110111010','1111111110111011','1111111110111100','1111111110111101'; 45 | '111111001','1111111110111110','1111111110111111','1111111111000000','1111111111000001','1111111111000010','1111111111000011','1111111111000100','1111111111000101','1111111111000110'; 46 | '111111010','1111111111000111','1111111111001000','1111111111001001','1111111111001010','1111111111001011','1111111111001100','1111111111001101','1111111111001110','1111111111001111'; 47 | '1111111001','1111111111010000','1111111111010001','1111111111010010','1111111111010011','1111111111010100','1111111111010101','1111111111010110','1111111111010111','1111111111011000'; 48 | '1111111010','1111111111011001','1111111111011010','1111111111011011','1111111111011100','1111111111011101','1111111111011110','1111111111011111','1111111111100000','1111111111100001'; 49 | '11111111000','1111111111100010','1111111111100011','1111111111100100','1111111111100101','1111111111100110','1111111111100111','1111111111101000','1111111111101001','1111111111101010'; 50 | '1111111111101011','1111111111101100','1111111111101101','1111111111101110','1111111111101111','1111111111110000','1111111111110001','1111111111110010','1111111111110011','1111111111110100'; 51 | '1111111111110101','1111111111110110','1111111111110111','1111111111111000','1111111111111001','1111111111111010','1111111111111011','1111111111111100','1111111111111101','1111111111111110'}; 52 | cont=0; 53 | qOutput=zeros(1024,1024); 54 | dctOutput=zeros(1024,1024); 55 | qMatrix=repmat(defaultQuantizationMatrix,128); 56 | % qMatrix2=qMatrix./2; 57 | % qMatrix3=qMatrix.*8; 58 | qMatrixforQuant=qMatrix.*scaleFactor; 59 | 60 | 61 | row=1; 62 | while (row<=1024) 63 | col=1; 64 | while(col<=1024) 65 | input=scaledImage(row:row+7,col:col+7); 66 | dctOutput(row:row+7,col:col+7)=dct2(input); 67 | col=col+8; 68 | cont=cont+1; 69 | end 70 | row=row+8; 71 | end 72 | 73 | %dctOutput=dct2(scaledImage); %We avoid bulk dct and do it blockwise 74 | qOutput=round(dctOutput./qMatrixforQuant); 75 | 76 | 77 | row=1; 78 | direction=0; %1-->top to bottom , 0 ---> bottom to top 79 | blkCount=0 80 | zigzagscan=zeros(128*128,64); 81 | while(row<=1024) 82 | col=1; 83 | while(col<=1024) 84 | blkCount=blkCount+1; 85 | %logic for traversing the block 86 | cnt=0; 87 | while(cnt<64) 88 | cnt=cnt+1; 89 | index=zigzagScanIndex(cnt); 90 | x=floor(index/10); 91 | y=index-(x*10); 92 | zigzagscan(blkCount,cnt) = qOutput(row+x-1,col+y-1); 93 | end 94 | col=col+8; 95 | end 96 | row=row+8; 97 | end 98 | 99 | 100 | blkCount=1; 101 | maxTupleCount=-1; 102 | maxTupleVectorSize=200; 103 | rleOutput=zeros(128*128,maxTupleVectorSize); 104 | previousDCCoeff=0; 105 | while(blkCount<=128*128) 106 | runLevelTuples=[]; 107 | runLevelTuplesFinal=[]; 108 | 109 | nonZeroIndices=find(zigzagscan(blkCount,:)~=0); 110 | nonZeroIndicesCount=length(nonZeroIndices); 111 | 112 | 113 | %adding the dc coefficient 114 | if(length(nonZeroIndices)>0 && nonZeroIndices(1)==1) 115 | runLevelTuples=cat(2,runLevelTuples,zigzagscan(blkCount,nonZeroIndices(1))); 116 | %dpcm of dc coeff. 117 | if(blkCount~=1) 118 | runLevelTuples(1)=previousDCCoeff-runLevelTuples(1); 119 | end 120 | previousDCCoeff= zigzagscan(blkCount,nonZeroIndices(1)); 121 | else 122 | runLevelTuples(1)=previousDCCoeff; 123 | previousDCCoeff=0; 124 | 125 | end 126 | 127 | 128 | i=2; 129 | while(i<=nonZeroIndicesCount) 130 | run=nonZeroIndices(i)-nonZeroIndices(i-1)-1; 131 | runLevelTuples=cat(2, runLevelTuples, run,zigzagscan(blkCount,nonZeroIndices(i))); 132 | i=i+1; 133 | end 134 | %adding eob 135 | runLevelTuples=cat(2,runLevelTuples,255,255); 136 | 137 | if(length(runLevelTuples)>maxTupleCount) 138 | maxTupleCount=length(runLevelTuples); 139 | end 140 | 141 | runLevelTuplesFinal=cat(2,runLevelTuples,zeros(1,maxTupleVectorSize-length(runLevelTuples))); 142 | rleOutput(blkCount,:)=runLevelTuplesFinal; 143 | blkCount=blkCount+1; 144 | end 145 | 146 | %end of huffman generation 147 | 148 | %Huffman Coding 149 | 150 | blkIndex=1; 151 | huffManOutput=cell(128*128,maxTupleVectorSize); 152 | while(blkIndex<=128*128) 153 | constHuffman={}; 154 | index=2; 155 | %dc encoding 156 | dcComp=rleOutput(blkIndex,1); 157 | if(dcComp==0) 158 | dcCategory=0; 159 | else 160 | dcCategory=floor(log2(abs(dcComp)))+1; 161 | end 162 | 163 | if(dcComp>0) 164 | baseCode=dec2bin(dcComp); 165 | else 166 | if(dcComp<0) 167 | baseCode=dec2bin(dcComp+(2^dcCategory)-1,dcCategory); 168 | else 169 | baseCode='0'; 170 | end 171 | end 172 | 173 | valueCode=huffmanCodesDC(dcCategory+1); 174 | constHuffman(1)=cellstr(baseCode); 175 | constHuffman(2)=cellstr(valueCode); 176 | 177 | %ac encoding 178 | while(index<=maxTupleVectorSize) 179 | run=rleOutput(blkIndex,index); 180 | 181 | c=rleOutput(blkIndex,index+1); 182 | category= floor(log2(abs(c)))+1; 183 | if(run==255 && c==255) 184 | constHuffman=cat(2,constHuffman,'1010'); 185 | break; 186 | else 187 | if(run>=15) 188 | run=15; 189 | end 190 | constHuffman=cat(2,constHuffman,huffmanCodesAC(run+1,category+1)); 191 | end 192 | index=index+2; 193 | end 194 | s=size(constHuffman); 195 | constHuffman=cat(2,constHuffman,cell(1,maxTupleVectorSize-s(2))); 196 | huffManOutput(blkIndex,:)=constHuffman(1,1:200); 197 | blkIndex=blkIndex+1; 198 | end 199 | 200 | blkIndex=1; 201 | totalBits=0; 202 | while(blkIndex<=128*128) 203 | index=1; 204 | while(index<=maxTupleVectorSize) 205 | totalBits=totalBits+size(huffManOutput(blkIndex,index)); 206 | if(strcmp(huffManOutput(blkIndex,index),'1010')) 207 | break; 208 | end 209 | index=index+1; 210 | end 211 | blkIndex=blkIndex+1; 212 | end 213 | 214 | CompressionRatio=totalBits/(1024*1024*8); 215 | %Start of Decoding 216 | 217 | %Huffman Decoding 218 | 219 | blkIndex=1; 220 | huffManDecodeOutput=zeros(128*128,maxTupleVectorSize); 221 | while(blkIndex<=128*128) 222 | huffManDecode=[]; 223 | encString=huffManOutput(blkIndex,:); 224 | %dc decoding 225 | category=lookup(huffmanCodesDC,encString(2)); 226 | estValue=bin2dec(encString(1)); 227 | if(estValue<(2^(category-1))) 228 | estValue=estValue+1-2^category; 229 | end 230 | huffManDecode(1)=estValue; 231 | %ac decoding 232 | index=3; 233 | while(index<=maxTupleVectorSize) 234 | if(strcmp(encString(index),'1010')) 235 | huffManDecode=cat(2,huffManDecode,[255 255]); 236 | break; 237 | else 238 | [index1,index2]=lookup(huffmanCodesAC,encString(index)); 239 | huffManDecode=cat(2,huffManDecode,[index1-1 index2-1]); 240 | end 241 | index=index+1; 242 | end 243 | s=size(huffManDecode); 244 | huffManDecode=cat(2,huffManDecode,zeros(1,maxTupleVectorSize-s(2))); 245 | 246 | huffManDecodeOutput(blkIndex,:)=huffManDecode(1,1:200); 247 | blkIndex=blkIndex+1; 248 | end 249 | %Run-length decoding 250 | 251 | blkCount=1; 252 | 253 | constZigZagMatrix=zeros(128*128,64); 254 | while(blkCount<=128*128) 255 | constructedZigZag=[]; 256 | runLengthTuples=rleOutput(blkCount,:); 257 | if(blkCount==1) 258 | constructedZigZag(1)=runLengthTuples(1); 259 | else 260 | constructedZigZag(1)=constZigZagMatrix(blkCount-1,1)-runLengthTuples(1); 261 | end 262 | 263 | i=2; 264 | while(i<=maxTupleVectorSize) 265 | 266 | if(runLengthTuples(i)<255) %regular tuples 267 | constructedZigZag=cat(2,constructedZigZag,zeros(1,runLengthTuples(i))); 268 | constructedZigZag=cat(2,constructedZigZag,runLengthTuples(i+1)); 269 | else %eob pad with zeros 270 | constructedZigZag=cat(2,constructedZigZag,zeros(1,64-length(constructedZigZag))); 271 | break; 272 | end 273 | 274 | i=i+2; 275 | end 276 | constZigZagMatrix(blkCount,:)=constructedZigZag; 277 | blkCount=blkCount+1; 278 | end 279 | 280 | 281 | %De-zigzag 282 | 283 | row=1; 284 | blkIndex=1; 285 | dezigzagOutput=zeros(1024,1024); 286 | while(row<=1024) 287 | col=1; 288 | while(col<=1024) 289 | i=1; 290 | while(i<=64) 291 | index=zigzagScanIndex(i); 292 | x=floor(index/10); 293 | y=index-x*10; 294 | dezigzagOutput(row+x-1,col+y-1)=constZigZagMatrix(blkIndex,i); 295 | i=i+1; 296 | end 297 | blkIndex=blkIndex+1; 298 | col=col+8; 299 | end 300 | 301 | row=row+8; 302 | end 303 | 304 | %De-Quantize 305 | dequantizeOutput=dezigzagOutput.*qMatrixforQuant; 306 | dequantizeOutput=dequantizeOutput./100; 307 | 308 | %Inverse-DCT 309 | 310 | finalOutput=zeros(1024,1024); 311 | row=1; 312 | while (row<=1024) 313 | col=1; 314 | while(col<=1024) 315 | input=dequantizeOutput(row:row+7,col:col+7); 316 | finalOutput(row:row+7,col:col+7)=idct2(input); 317 | col=col+8; 318 | cont=cont+1; 319 | end 320 | row=row+8; 321 | end 322 | 323 | %finalOutput=idct2(dequantizeOutput); %We avoid bulk inverse-DCT and do it 324 | %blockwise 325 | % 326 | 327 | figure('name','CompressedImage'); 328 | imshow(finalOutput); 329 | 330 | 331 | %PSNR calculation 332 | 333 | diff=(double(finalOutput.*100)-double(scaledImage)).^2; 334 | MSE=sum(diff(:))./(1024*1024); 335 | PSNR=10*log10(255*255/MSE); 336 | 337 | 338 | end 339 | 340 | function [index1,index2]=lookup(input,key) 341 | rowCount=size(input(:,1)); 342 | colCount=size(input(1,:)); 343 | index1=1; 344 | while(index1<=rowCount) 345 | index2=1; 346 | while(index2<=colCount) 347 | if(strcmp(input(index1,index2),key)) 348 | break; 349 | end 350 | index2=index2+1; 351 | end 352 | index1=index1+1; 353 | end 354 | end --------------------------------------------------------------------------------