20

Tôi đang cố gắng viết chức năng của riêng mình để mở rộng hình ảnh đầu vào bằng cách sử dụng thuật toán nội suy lân cận gần nhất. Phần xấu là tôi có thể thấy nó hoạt động như thế nào nhưng không thể tìm thấy thuật toán. Tôi sẽ biết ơn vì sự giúp đỡ nào.Thuật toán nội suy lân cận gần nhất trong MATLAB

Đây là những gì tôi đã cố gắng để mở rộng các hình ảnh đầu vào bằng hệ số 2:

function output = nearest(input) 
[x,y]=size(input); 
output = repmat(uint8(0),x*2,y*2); 
[newwidth,newheight]=size(output); 
for i=1:y 
    for j=1:x 
     xloc = round ((j * (newwidth+1))/(x+1)); 
     yloc = round ((i * (newheight+1))/(y+1)); 
     output(xloc,yloc) = input(j,i); 
    end 
end 

Đây là kết quả sau khi Mark 's đề nghị alt text

+0

Xin lỗi, không biết những gì tôi đã suy nghĩ - bạn cần phải lặp qua các đầu ra, không đầu vào, vì đầu ra lớn hơn. Và trong trường hợp đó, công thức của tôi sẽ cần được đảo ngược. –

Trả lời

19

Một khi trở lại tôi đã đi qua mã của imresize chức năng trong MATLAB Image Processing Toolbox để tạo ra một phiên bản đơn giản cho chỉ nội suy lân cận gần nhất của hình ảnh. Dưới đây là làm thế nào nó sẽ được áp dụng cho vấn đề của bạn:

%# Initializations: 

scale = [2 2];    %# The resolution scale factors: [rows columns] 
oldSize = size(inputImage);     %# Get the size of your image 
newSize = max(floor(scale.*oldSize(1:2)),1); %# Compute the new image size 

%# Compute an upsampled set of indices: 

rowIndex = min(round(((1:newSize(1))-0.5)./scale(1)+0.5),oldSize(1)); 
colIndex = min(round(((1:newSize(2))-0.5)./scale(2)+0.5),oldSize(2)); 

%# Index old image to get new image: 

outputImage = inputImage(rowIndex,colIndex,:); 

Một lựa chọn khác là sử dụng được xây dựng trong interp2 chức năng, mặc dù bạn đã đề cập không muốn sử dụng các chức năng tích hợp sẵn trong một trong những bình luận của bạn.

EDIT: GIẢI THÍCH

Trong trường hợp có ai quan tâm, tôi nghĩ rằng tôi muốn giải thích cách giải pháp trên hoạt động ...

newSize = max(floor(scale.*oldSize(1:2)),1); 

Thứ nhất, để có được những hàng và cột kích thước mới kích thước hàng và cột cũ được nhân với hệ số tỷ lệ. Kết quả này được làm tròn xuống số nguyên gần nhất với floor. Nếu yếu tố quy mô nhỏ hơn 1, bạn có thể kết thúc với một trường hợp kỳ lạ của một trong những giá trị kích thước là 0, đó là lý do cuộc gọi đến max ở đó để thay thế bất cứ điều gì ít hơn 1 với 1.

rowIndex = min(round(((1:newSize(1))-0.5)./scale(1)+0.5),oldSize(1)); 
colIndex = min(round(((1:newSize(2))-0.5)./scale(2)+0.5),oldSize(2)); 

Tiếp theo, một bộ chỉ mục mới được tính cho cả hàng và cột. Đầu tiên, một tập hợp các chỉ mục cho hình ảnh được lấy mẫu được tính toán: 1:newSize(...). Mỗi pixel hình ảnh được coi là có chiều rộng nhất định, chẳng hạn pixel 1 kéo dài từ 0 đến 1, pixel 2 kéo dài từ 1 đến 2, v.v. Do đó, "tọa độ" của pixel được coi là trung tâm, đó là lý do tại sao 0,5 được trừ khỏi các chỉ số. Các tọa độ này sau đó được chia cho hệ số tỷ lệ để đưa ra một tập hợp các tọa độ điểm ảnh trung tâm cho ảnh gốc, sau đó có 0,5 được thêm vào chúng và được làm tròn để có được một tập hợp các chỉ số nguyên cho ảnh gốc. Cuộc gọi đến min đảm bảo rằng không có chỉ số nào trong số này lớn hơn kích thước hình ảnh gốc oldSize(...).

outputImage = inputImage(rowIndex,colIndex,:); 

Cuối cùng, hình ảnh upsampled mới được tạo ra bằng cách đơn giản chỉ mục vào ảnh gốc.

+0

hoạt động tuyệt vời, cảm ơn! – Hellnar

+0

@Hellnar: Rất vui được trợ giúp! Tôi cũng chỉ cập nhật mã vì vậy nó sẽ làm việc cho các yếu tố quy mô không nguyên cũng như cho hình ảnh thang độ xám hoặc RGB. – gnovice

0

Bạn chỉ cần một công thức tổng quát hơn để tính xloc và yloc.

xloc = (j * (newwidth+1))/(x+1); 
yloc = (i * (newheight+1))/(y+1); 

Giả định biến của bạn có đủ phạm vi cho kết quả nhân.

2

MATLAB đã thực hiện nó cho bạn. Sử dụng imresize:

output = imresize(input,size(input)*2,'nearest'); 

hoặc nếu bạn muốn mở rộng quy mô cả x & y như nhau,

output = imresize(input,2,'nearest'); 
+2

Tôi đã biết chức năng dựng sẵn, nhưng tôi cần phải đạt được điều này bằng mã của riêng tôi. cảm ơn – Hellnar

+1

Rất tiếc, không biết! Rất vui được thấy bạn tìm thấy câu trả lời của bạn. – Jacob

20

Câu trả lời này giải thích rõ ràng hơn là cố gắng súc tích và hiệu quả. Tôi nghĩ rằng giải pháp của gnovice là tốt nhất trong lĩnh vực đó. Trong trường hợp bạn đang cố gắng hiểu cách hoạt động, hãy đọc ...

Bây giờ vấn đề với mã của bạn là bạn đang lập bản đồ vị trí từ hình ảnh đầu vào đến hình ảnh đầu ra, đó là lý do tại sao bạn nhận được điểm số đầu ra. Hãy xem xét một ví dụ nơi hình ảnh đầu vào là tất cả màu trắng và đầu ra khởi tạo màu đen, chúng tôi nhận được những điều sau đây:

screenshot

Những gì bạn nên làm là điều ngược lại (từ đầu ra đầu vào). Để minh họa, hãy xem xét các ký hiệu sau:

1   c   1     scaleC*c 
+-----------+ 1  +----------------------+ 1 
| |  |   |  |    | 
|----o  | <=== |  |    | 
| (ii,jj) |   |--------o    | 
+-----------+ r  |  (i,j)   | 
    inputImage   |      | 
         |      | 
         +----------------------+ scaleR*r 
          ouputImage 

Note: I am using matrix notation (row/col), so: 
    i ranges on [1,scaleR*r] , and j on [1,scaleC*c] 
    and ii on [1,r], jj on [1,c] 

Ý tưởng là cho mỗi vị trí (i,j) trong hình ảnh đầu ra, chúng tôi muốn để ánh xạ nó vào vị trí "gần nhất" trong các tọa độ hình ảnh đầu vào. Vì đây là một bản đồ đơn giản chúng ta sử dụng công thức mà các bản đồ một cho x-y (cho tất cả các params khác):

x-minX  y-minY 
--------- = --------- 
maxX-minX maxY-minY 

trong trường hợp của chúng tôi, xi/j phối hợp và yii/jj danh từ: Tọa độ. Do đó thay thế cho mỗi ban cho chúng ta:

jj = (j-1)*(c-1)/(scaleC*c-1) + 1 
ii = (i-1)*(r-1)/(scaleR*r-1) + 1 

Đưa mảnh lại với nhau, chúng tôi nhận được đoạn mã sau:

% read a sample image 
inputI = imread('coins.png'); 
[r,c] = size(inputI); 
scale = [2 2];  % you could scale each dimension differently 

outputI = zeros(scale(1)*r,scale(2)*c, class(inputI)); 

for i=1:scale(1)*r 
    for j=1:scale(2)*c 
     % map from output image location to input image location 
     ii = round((i-1)*(r-1)/(scale(1)*r-1)+1); 
     jj = round((j-1)*(c-1)/(scale(2)*c-1)+1); 

     % assign value 
     outputI(i,j) = inputI(ii,jj); 
    end 
end 

figure(1), imshow(inputI) 
figure(2), imshow(outputI) 
+0

Giải pháp của gnovice nhanh gấp 10 lần. Tuy nhiên, cảm ơn bạn đã giải thích! – Wok

+0

Khi một hình ảnh tôi được chia tỷ lệ bằng cách sử dụng hàng xóm gần nhất với Izoom, và sau đó Izoom bị thu hẹp bởi cùng một yếu tố, chúng tôi lấy lại hình ảnh ban đầu I. Bây giờ, bằng trực giác, tôi hiểu rằng vì chúng tôi chỉ sao chép pixel và không phải trung bình, điều này là khá tự nhiên, nhưng tôi không thể tìm thấy một bằng chứng nghiêm ngặt hơn. Tôi đã hy vọng một ai đó ở đây có thể cho tôi một vài gợi ý về điều này. – idexi