2016-10-16 8 views
6

टीएल; डीआर: एक आयताकार छवि को एक सर्कल में फसल करने का सबसे प्रभावी तरीका क्या है?छवि को सर्कल करने के लिए सबसे प्रभावी तरीका (आर में)?

स्पष्टीकरण/पृष्ठभूमि:

मैं कुछ कोड पर काम कर रहा हूँ आर में है कि डिफ़ॉल्ट rectanges बजाय हलकों/वर्गों के रूप में Spotify कलाकार छवियों को प्रदर्शित करेगा। मुझे कोई संकुल या आदेश नहीं मिला जो आर में विशेष रूप से एक सर्कल में छवियों को फसल करता है, इसलिए मैंने अपना स्वयं का फ़ंक्शन लिखा, circ, जो 3-आयामी (या 4-आयामी) आरजीबी (ए) सरणी पढ़ता है और उन्हें फसल करता है हर अद्वितीय वाई के लिए एक्स मान निर्धारित करने के लिए the parametric equation of a circle का उपयोग करके सर्कल। यहाँ मेरी psuedocode है:

Given an RGB(A) array: 
    Find the center of the image, radius = min(x coord, y coord) 
    Pre-crop the image to a square of dimensions 2r x 2r 
    For every unique y value: 
     Determine the x coordinates on the circle 
     Make pixels outside of the circle transparent 
    Return the cropped image as an RGBA array 

इस समारोह मेरे पिछले एक है, जो हर पिक्सेल की स्थिति की जाँच करता है, तो इसके अंदर या सर्कल के बाहर था देखने के लिए खत्म हो गया एक जबरदस्त सुधार है, लेकिन मैं अब भी लगता है जैसे कि यह तेज किया जा सकता है आगे बढ़ो

क्या कोई तरीका है कि मैं उन सभी के बजाय वाई-मानों का आधा हिस्सा देख सकता हूं, और सर्कल में दर्पण कर सकता हूं? क्या कोई वास्तविक क्रॉपिंग फ़ंक्शन है जिसका मैं उपयोग कर सकता हूं? किसी भी और सभी मदद की बहुत सराहना की है!

संपादित कुछ कॉपी-पेस्ट रन कोड (धन्यवाद @lukeA) जोड़ने के लिए:

मेरी मूल फसल विधि:

circ = function(a){ 
    # First part of the function finds the radius of the circle and crops the image accordingly 
    xc = floor(dim(a[,,1])[2]/2) # X coordinate of the center 
    yc = floor(dim(a[,,1])[1]/2) # Y coordinate of the center 
    r = min(xc, yc) - 1 # Radius is the smaller of the two -1 to avoid reading nonexistent data 
    ma = array(data = c(a[,,1][(yc-r):(yc+r),(xc-r):(xc+r)], # Read in the cropped image 
         a[,,2][(yc-r):(yc+r),(xc-r):(xc+r)], # Of dimensions 2r x 2r, centered 
         a[,,3][(yc-r):(yc+r),(xc-r):(xc+r)], # Around (xc, yc) 
         rep(1,length(a[,,1][(yc-r):(yc+r),(xc-r):(xc+r)]))), # Add fourth alpha layer 
      dim = c(length((yc-r):(yc+r)),length((xc-r):(xc+r)),4)) 

    if(yc > xc) yc = xc else if(xc > yc) xc = yc # Re-evaluate your center for the cropped image 
    xmax = dim(ma[,,1])[2]; ymax = dim(ma[,,1])[1] # Find maximum x and y values 

    # Second part of the function traces circle by the parametric eqn. and makes outside pixels transparent 
    for(y in 1:ymax){ # For every y in the cropped image 
    theta = asin((y - yc)/r) # y = yc + r * sin(theta) by parametric equation for a circle 
    x = xc + r * cos(theta) # Then we can find the exact x coordinate using the same formula 
    x = which.min(abs(1:xmax - x)) # Find which x in array is closest to exact coordinate 
    if(!x - xc == 0 && !xmax - x == 0){ # If you're not at the "corners" of the circle 
     ma[,,4][y,c(1:(xmax-x), (x+1):xmax)] = 0 # Make pixels on either side of the circle trans. 
    } else if(!xmax - x == 0) ma[,,4][y,] = 0 # This line makes tops/bottoms transparent 
    } 
    return(ma) 
} 

library(jpeg) 
a = readJPEG("http://1.bp.blogspot.com/-KYvXCEvK9T4/Uyv8xyDQnTI/AAAAAAAAHFY/swaAHLS-ql0/s1600/pink-smiley-face-balls-laughing-HD-image-for-faacebook-sharing.jpg") 
par(bg = "grey"); plot(1:2, type="n") # Color background to check transparency 
rasterImage(circ(a),1,1,2,2) 

संशोधित संस्करण (धन्यवाद @dww):

dwwcirc = function(a){ 
    # First part of the function finds the radius of the circle and crops the image accordingly 
    xc = floor(dim(a[,,1])[2]/2) # X coordinate of the center 
    yc = floor(dim(a[,,1])[1]/2) # Y coordinate of the center 
    r = min(xc, yc) - 1 # Radius is the smaller of the two -1 to avoid reading nonexistent data 
    ma = array(data = c(a[,,1][(yc-r):(yc+r),(xc-r):(xc+r)], # Read in the cropped image 
         a[,,2][(yc-r):(yc+r),(xc-r):(xc+r)], # Of dimensions 2r x 2r, centered 
         a[,,3][(yc-r):(yc+r),(xc-r):(xc+r)], # Around (xc, yc) 
         rep(1,length(a[,,1][(yc-r):(yc+r),(xc-r):(xc+r)]))), # Add fourth alpha layer 
      dim = c(length((yc-r):(yc+r)),length((xc-r):(xc+r)),4)) 

    if(yc > xc) yc = xc else if(xc > yc) xc = yc # Re-evaluate your center for the cropped image 
    xmax = dim(ma[,,1])[2]; ymax = dim(ma[,,1])[1] # Find maximum x and y values 

    x = rep(1:xmax, ymax) # Vector containing all x values 
    y = rep(1:ymax, each=xmax) # Value containing all y values 
    r2 = r^2 
    ma[,,4][which(((x-xc)^2 + (y-yc)^2) > r2)] = 0 
    return(ma) 
} 

library(jpeg) 
a = readJPEG("http://1.bp.blogspot.com/-KYvXCEvK9T4/Uyv8xyDQnTI/AAAAAAAAHFY/swaAHLS-ql0/s1600/pink-smiley-face-balls-laughing-HD-image-for-faacebook-sharing.jpg") 
par(bg = "grey"); plot(1:2, type="n") # Color background to check transparency 
rasterImage(dwwcirc(a),1,1,2,2) 

मैजिक और प्लॉट्रिक्स का उपयोग कर संस्करण (धन्यवाद @lukeA और @hrbrmstr):

library(plotrix) 
jpeg(tf <- tempfile(fileext = "jpeg"), 1000, 1000) 
par(mar = rep(0,4), yaxs="i", xaxs = "i") 
plot(0, type = "n", ylim = c(0, 1), xlim = c(0,1), axes=F, xlab=NA, ylab=NA) 
draw.circle(.5,.5,.5,col="black") 
dev.off() 

library(magick) 
img = image_read("http://1.bp.blogspot.com/-KYvXCEvK9T4/Uyv8xyDQnTI/AAAAAAAAHFY/swaAHLS-ql0/s1600/pink-smiley-face-balls-laughing-HD-image-for-faacebook-sharing.jpg") 
mask = image_read(tf) 
radius = min(c(image_info(img)$width, image_info(img)$height)) 
mask = image_scale(mask, as.character(radius)) 

par(bg = "grey"); plot(1:2, type="n") 
rasterImage(as.raster(image_composite(image = mask, composite_image = img, operator = "plus")),1,1,2,2) 
+0

के साथ अपने समारोह के 2 भाग की जगह आप इमेजर :: imsub क्रॉप कर सकते हैं, लेकिन यह केवल आयताकार तर्क लेता है। आप जो भी कर रहे हैं उसके साथ रहना होगा, लेकिन यह आपके ह्युरिस्टिक के एक कदम को काट देगा। – shayaa

+0

क्या आपको इस तरह आर को हैक करने की कोशिश करने के बजाय वास्तविक छवि प्रसंस्करण उपकरण का उपयोग नहीं करना चाहिए? –

+0

[मैं केवल टीएल पढ़ता हूं; डॉ] रास्टर मास्क बनाने के लिए ग्रिड ग्राफिक्स के साथ उदाहरण हैं – baptiste

उत्तर

2

आप अपने circ समारोह के प्रदर्शन में सुधार कर सकते हैं अगर आप अपने सरणी पर एक vectorised सबसेट असाइन आपरेशन करते हैं (बजाय लूपिंग का) इस तथ्य का उपयोग करते हुए कि (x-xc)^2 +(y-yc)^2 > r^2 किसी मंडली के बाहर बिंदुओं के लिए।

ऐसा करने के लिए,

# Second part of the function traces circle by... 
    x = rep(1:xmax, ymax) 
    y = rep(1:ymax, each=xmax) 
    r2 = r^2 
    ma[,,4][which(((x-xc)^2 + (y-yc)^2) > r2)] <- 0 
    return(ma) 
+1

वाह! मैंने कोशिश की और रनटाइम को [सभ्य आकार के जेपीईजी] पर जांचें (http://1.bp.blogspot.com/-KYvXCEvK9T4/Uyv8xyDQnTI/AAAAAAAAHFY/swaAHLS-ql0/s1600/pink-smiley-face-balls- हँसते हुए -HD छवि के लिए faacebook-sharing.jpg)। 'Proc.time()' के अनुसार, यह एक-दसवां से भी कम समय (16.887 से 1.232 सेकेंड तक) लेता है जो पागल है। मैं इसे तुरंत लागू कर दूंगा, धन्यवाद! –

+0

बढ़िया, खुशी हुई इससे मदद मिली। बस एक सिर-अप। एक्स और वाई * की परिभाषाओं को एक्सचेंज करने की आवश्यकता है, भले ही आपकी सरणी कॉलम या पंक्ति क्रम में परिभाषित की गई हो। यदि वे गलत तरीके से गोल हैं तो यह एक आसान फिक्स है - (यदि आपको गैर स्क्वायर छवियों के लिए केंद्र से ऑफसेट हो जाता है तो आपको पता चलेगा कि क्या इसे tweaking की आवश्यकता है)। अगर यह होता है तो मुझे बताएं कि मैं – dww

+0

के अनुसार उत्तर को ठीक कर दूंगा, मैंने मूल रूप से उससे अधिक कुछ केंद्र नहीं देखा है (त्रिज्या को परिभाषित करते समय -1 के लिए धन्यवाद), लेकिन ऐसा लगता है कि आप सरणी में विशिष्ट कक्षों को कॉल करते हैं ए, आयाम डी 'एक [, डी] [वाई, एक्स]', तो मुझे लगता है कि आप सुनहरे हैं। –

4

मुझे "दक्षता" के बारे में पता नहीं है, लेकिन मैं यहां पहिया को फिर से नहीं बदलूंगा। जैसा @hrbrmstr द्वारा टिप्पणी में सुझाव दिया है, तो आप magick कोशिश करना चाहते हो सकता है, जो आप सब लचीलापन आपको आवश्यकता हो सकती देता है:

png(tf <- tempfile(fileext = ".png"), 1000, 1000) 
par(mar = rep(0,4), yaxs="i", xaxs="i") 
plot(0, type = "n", ylim = c(0,1), xlim=c(0,1), axes=F, xlab=NA, ylab=NA) 
plotrix::draw.circle(.5,0.5,.5, col="black") 
dev.off() 

library(magick) 
fn <- "https://www.gravatar.com/avatar/f57aba01c52e5c67696817eb87df84f2?s=328&d=identicon&r=PG&f=1" 
img <- image_read(fn) 
mask <- image_read(tf) 
mask <- image_scale(mask, as.character(image_info(img)$width)) 

अब

img 

enter image description here

mask 

enter image description here

image_composite(mask, img, "plus") 

enter image description here

image_composite(mask, img, "minus") 

enter image description here

कुछ अन्य composite operators:

# https://www.imagemagick.org/Magick++/Enumerations.html#CompositeOperator 
ops <- c("over", "in", "out", "atop", "xor", "plus", "minus", "add", "difference", "multiply") 
for (op in ops) { 
    print(image_composite(img, mask, op)) 
    print(op) 
    readline() 
} 
+0

मैं इसे अभी आज़मा रहा हूं। मेरे पास आपके लिए कुछ प्रश्न हैं जबकि मैं अपने लिए पता लगाने की कोशिश करता हूं। –

+0

ओह, मैं टिप्पणी करने के लिए नया हूं - मुझे एहसास नहीं हुआ कि प्रवेश पोस्ट पोस्ट करेगा। पहला यह है कि स्पॉटिफाइव अपने कलाकार चित्रों को जेपीजीएस के रूप में रखता है, पीएनजी नहीं, लेकिन मुझे इसके बारे में काम करना चाहिए, मुझे लगता है। दूसरा सवाल यह है कि "माइनस" आपके द्वारा मुखौटा क्षेत्र को हटा देता है (या अदृश्य प्रस्तुत करता है)? या यह रंग के विपरीत के रूप में, यह रखता है? धन्यवाद –

+0

# 1 वही काम करता है, हाँ। # 2 "शून्य" _ "समग्र छवि - छवि है, ओवरफ्लो शून्य पर फसल के साथ। मैट चैनल को अनदेखा किया जाता है (255 पर सेट, पूर्ण कवरेज)।" _। तो, काला मुखौटा का मतलब है कि यह पूरी तरह से दृश्यमान है। (ग्रे इसे अंधेरा करता है। सफेद काला है।) – lukeA

संबंधित मुद्दे