プレースホルダ

# ダメ
my $sth = $dbh->prepare('SELECT * FROM image_tag WHERE tag IN(?, ?) GROUP BY image HAVING count(image) == ?');
$sth->execute(10, 42, 2);

# イイ!
my $sth = $dbh->prepare('SELECT * FROM image_tag WHERE tag IN(?, ?) GROUP BY image HAVING count(image) == 2');
$sth->execute(10, 42);

なので、

my $rs = $schema->resultset('ImageTag')->search(
    { tag => {in => [10, 42]} },
    {
        group_by => ['image'],
        having => {'count(image)' => {'==', 2}},
    }
);

じゃなくて、

my $rs = $schema->resultset('ImageTag')->search(
    { tag => {in => [10, 42]} },
    {
        group_by => ['image'],
        having => {'count(image)' => \ '== 2'},
    }
);

こうやらないといけない(少なくともSQLiteを使う限りは。他のRDBだとまた違うかも)。

追記

ん、HAVING句で使えないんじゃなくて、集約関数使ってるからプレースホルダ使えないのかな。ためしに、

my $sth = $dbh->prepare('SELECT * FROM image_tag WHERE tag IN(?, ?) GROUP BY image HAVING image != ?');
$sth->execute(10, 42, 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX');

こんなの発行してみたら、思った通りの結果が返ってきたし。いや、まあ、実際にこういうの発行することはないだろうけど。