Skip to content

Instantly share code, notes, and snippets.

@nvs-abhilash
Last active July 23, 2024 15:05
Show Gist options
  • Save nvs-abhilash/75a3920980fe32ffd4754bc205362125 to your computer and use it in GitHub Desktop.
Save nvs-abhilash/75a3920980fe32ffd4754bc205362125 to your computer and use it in GitHub Desktop.
Helper function to resize and rotate contours using OpenCV
import cv2
import numpy as np
def cart2pol(x, y):
theta = np.arctan2(y, x)
rho = np.hypot(x, y)
return theta, rho
def pol2cart(theta, rho):
x = rho * np.cos(theta)
y = rho * np.sin(theta)
return x, y
def rotate_contour(cnt, angle):
M = cv2.moments(cnt)
cx = int(M['m10']/M['m00'])
cy = int(M['m01']/M['m00'])
cnt_norm = cnt - [cx, cy]
coordinates = cnt_norm[:, 0, :]
xs, ys = coordinates[:, 0], coordinates[:, 1]
thetas, rhos = cart2pol(xs, ys)
thetas = np.rad2deg(thetas)
thetas = (thetas + angle) % 360
thetas = np.deg2rad(thetas)
xs, ys = pol2cart(thetas, rhos)
cnt_norm[:, 0, 0] = xs
cnt_norm[:, 0, 1] = ys
cnt_rotated = cnt_norm + [cx, cy]
cnt_rotated = cnt_rotated.astype(np.int32)
return cnt_rotated
import cv2
import numpy as np
def scale_contour(cnt, scale):
M = cv2.moments(cnt)
cx = int(M['m10']/M['m00'])
cy = int(M['m01']/M['m00'])
cnt_norm = cnt - [cx, cy]
cnt_scaled = cnt_norm * scale
cnt_scaled = cnt_scaled + [cx, cy]
cnt_scaled = cnt_scaled.astype(np.int32)
return cnt_scaled
@Spawnfile
Copy link

Thank you for all good guide for rotating countours with openCV. Want to ask you about subtracting ( normalizing ) countour pixel coordinates. I did not get why exactly you did that, can you explain ?

@helviorhild
Copy link

Thank you, I using your code to align contour for 2D packing problem

@helviorhild
Copy link

helviorhild commented Jul 23, 2024

I translate your code to C++

#include <algorithm>
#include <cmath>
#include <array>
#include <math.h>
using namespace cv;
using namespace std;
array<double,2> cart2pol(int &x,int &y){
    double theta=atan2(y,x);
    double rho=hypot(x,y);
    return array<double,2>{{theta,rho}};
}

Point pol2cart(double &theta,double  &rho)
{
    int x=ceil(rho*cos(theta));
    int y=ceil(rho*sin(theta));
    return Point(x,y);
}
  
vector<Point> rotate_contour(vector<Point> &cnt,float &angle){
Moments M=moments(cnt);
int cx= int(M.m10/M.m00);
int cy = int(M.m01/M.m00);
vector<Point>cnt_rot;
cnt_rot.reserve(cnt.size());
Point pcenter(cx,cy);
for (Point icnt : cnt)
{  
    Point tmp(icnt-pcenter);
   array<double,2> thetasRho=cart2pol(tmp.x,tmp.y);
   thetasRho[0]=thetasRho[0]+angle*M_PI/180;//no rounded to 360 (2*PI)
    cnt_rot.push_back(pol2cart(thetasRho[0],thetasRho[1])+pcenter);
}
return (cnt_rot); 
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment