Auto Detect Image for 360 nature in PHP
Asked Answered
C

2

6

I am rendering a Property Detail page like below (can be accessed Here) enter image description here

I have an image slider and a 360 Image viewer. Currently the user uploads both type of images manually i.e plain images from one interface and 360 images from other interface. I check if the property has 360 images and display them using the panorama viewer.

I use the following Controller to upload the 360 Images which is similar to uploading plain images.

public function upload_360_images()
{
    if($this->session->userdata['id'] && $this->session->userdata['type']=='user')
    {
        if($_FILES)
        {
            if(isset($_FILES['files'])){
                $data['errors']= array();
                $extensions = array("jpeg","jpg","png");

                foreach($_FILES['files']['tmp_name'] as $key => $tmp_name ){

                    $file_name = $key.$_FILES['files']['name'][$key];
                    $file_size =$_FILES['files']['size'][$key];
                    $file_tmp =$_FILES['files']['tmp_name'][$key];
                    $file_type=$_FILES['files']['type'][$key];
                    /*$file_ext=explode('.',$_FILES['image']['name'][$key]) ;
                    $file_ext=end($file_ext);*/
                    $i=1;
                    if($file_size > 7097152){
                        $data['errors'][$i]='File '.$i.' size must be less than 7 MB';
                        $i++;
                    }

                    $desired_dir="uploads";
                    if(empty($data['errors'])==true){
                        if(is_dir($desired_dir)==false){
                            mkdir("$desired_dir", 0700);        // Create directory if it does not exist
                        }
                        if(is_dir("$desired_dir/".$file_name)==false){
                            move_uploaded_file($file_tmp,"uploads/".$file_name);
                            $this->post_model->add360Image('property_360_images',$file_name,$this->uri->segment(3));
                        }else{                                  //rename the file if another one exist
                            $new_dir="uploads/".$file_name.time();
                            rename($file_tmp,$new_dir) ;
                        }

                    }else{
                        $data['contact']=$this->admin_model->getContactDetails();
                        $data['images']=$this->post_model->getProperty360Images($this->uri->segment(3));
                        $data['title']='My Profile Image';
                        $this->load->view('site/static/head',$data);
                        $this->load->view('site/static/header');
                        $this->load->view('site/content/upload_360_images');
                        $this->load->view('site/static/footer');
                        $this->load->view('site/static/footer_links');
                    }
                }
                if(empty($data['errors']))
                {
                    redirect(base_url().'dashboard');
                }
                else
                {
                    $data['contact']=$this->admin_model->getContactDetails();
                    $data['images']=$this->post_model->getProperty360Images($this->uri->segment(3));
                    $data['title']='My Profile Image';
                    $this->load->view('site/static/head',$data);
                    $this->load->view('site/static/header');
                    $this->load->view('site/content/upload_360_images');
                    $this->load->view('site/static/footer');
                    $this->load->view('site/static/footer_links');
                }
            }

        }
        else
        {
            $data['contact']=$this->admin_model->getContactDetails();
            $data['images']=$this->post_model->getProperty360Images($this->uri->segment(3));
            $data['title']='My Profile Image';
            $this->load->view('site/static/head',$data);
            $this->load->view('site/static/header');
            $this->load->view('site/content/upload_360_images');
            $this->load->view('site/static/footer');
            $this->load->view('site/static/footer_links');
        }

    }
    else
    {
        redirect(base_url().'user/login');
    }

}

Please ignore the long code, this code is from a production so i have to put a lot of checks and conditions.

Problem Now my employer wants me to use single interface to upload both plain and 360 images and detect the nature of the image using some detection algorithm and then display the image in the same image slider which I am using for static/plain images.

Research

I read this thread on Stackoverflow which made a little sense about reading the meta data of the file using EXIF tool but that makes this process pretty manual.

Question

I want to automate that image reading use it in my php image upload code or write that detection algorithm in a function which gets image name as parameter and return the image type as plain or 360. Based on that return I can easily render the views. So My question is how to do that detection in php?

Claar answered 27/2, 2017 at 7:14 Comment(2)
have a look at exiftool - it shows "Field of View" meta information from the exif tags. Although there's no guarantee of its presence...Canakin
Perhaps the EXIF PHP Extension wasn't around when this question was asked, but there's no reason reading or creating EXIF metadata needs to be a manual process.Legalism
N
4

According to Facebook 360 Group:

There isn't yet a standard for tagging a photo as containing 360 content.

It suggest that you look for the EXIF tag

Projection Type : equirectangular

You can also look for

Use Panorama Viewer : True

Those two tags are present on photos taken with my LG 360.

Natch answered 7/8, 2017 at 20:19 Comment(1)
Valid equirectangular images will also have a 2:1 aspect ratio.Legalism
G
2

I faced a similar problem for Unity3D platform, but I figured this considering that Equirectangular images usually have proportion as 2:1.

Likely width 2000px and height 1000px(I already have seen software generating heights a bit higher).

Here is the pseudo code, keep in mind that this code considers posX and posY starting from bottom left:

//this is how much the image should be close the 2:1 proportion, or 0.5-proportionThreshold.
proportionThreshold = 0.01;

//images smaller than this should not have resolution enough to be a panorama.
//it is important here to 
minimumWidth = 2000;
minimumHeight = 1080;

//in case of the image is not a panorama, this variable determines the maximum size it could be projected
maxFill = 0.65;

//what is the amount of the view the pamorama should view:
scaleX = 1;
scaleY = 1;

//where the panorama should be positioned in the view:
posX = 0;
posY = 0;

currentWidth = source.width;
currentHeight = source.height;

if(isFullPanorama()){
    Log("Full Panorama");
    //the variables are already set for that
}else if(isPartialPanorama()){
    Log("Partial Panorama");
    scale = currentHeight/currentWidth * 2f;
    scaleX = 1;
    scaleY = scale;
    posX = 0;
    posY = 0.5-scale/2;
}else{
    Debug.Log("Not Panorama");
    proportion = currentHeight/currentWidth;
    w = currentWidth > minimumWidth*maxFill ? minimumWidth*maxFill : currentWidth;
    scaleX = w / minimumWidth / 2;
    scaleY = scaleX * proportion * 2;
    if(scaleY>1) {
        h = currentHeight > minimumHeight*maxFill ? minimumHeight*maxFill : currentHeight;
        scaleY = h / minimumHeight / 2;
        scaleX = scaleY * proportion / 2;
    }
    posX = 0.5-scaleX/2;
    posY = 0.5-scaleY/2;
}

bool isFullPanorama(){
    proportion = currentHeight/currentWidth;
    return proportion>=0.5-proportionThreshold &&
    proportion<=0.5+proportionThreshold &&
    source.height >= minimumHeight;
}

bool isPartialPanorama(){
    return currentHeight/currentWidth<=0.5 &&
    source.width >= minimumWidth;
}
Goulet answered 14/9, 2017 at 15:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.